parent
09fba4a0b5
commit
f8dfc1ce1f
@ -0,0 +1,9 @@
|
|||||||
|
[buildfile]
|
||||||
|
includes = //DEFS
|
||||||
|
|
||||||
|
[project]
|
||||||
|
ignore = .git, .ml, .mli
|
||||||
|
|
||||||
|
[java]
|
||||||
|
source_level = 8
|
||||||
|
target_level = 8
|
@ -0,0 +1,47 @@
|
|||||||
|
---
|
||||||
|
AccessModifierOffset: -1
|
||||||
|
AlignEscapedNewlinesLeft: true
|
||||||
|
AlignTrailingComments: false
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakBeforeMultilineStrings: true
|
||||||
|
AlwaysBreakTemplateDeclarations: true
|
||||||
|
BinPackArguments: false
|
||||||
|
BinPackParameters: false
|
||||||
|
BreakBeforeBinaryOperators: false
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
ColumnLimit: 80
|
||||||
|
CommentPragmas: '^@atd'
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
ExperimentalAutoDetectBinPacking: true
|
||||||
|
IndentCaseLabels: true
|
||||||
|
IndentFunctionDeclarationAfterType: false
|
||||||
|
IndentWidth: 2
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
ObjCSpaceBeforeProtocolList: false
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 10
|
||||||
|
PenaltyBreakComment: 1000
|
||||||
|
PenaltyBreakFirstLessLess: 20
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 200
|
||||||
|
PointerAlignment: Left
|
||||||
|
SortIncludes: false
|
||||||
|
SpaceAfterControlStatementKeyword: true
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
Standard: Cpp11
|
||||||
|
TabWidth: 8
|
||||||
|
UseTab: Never
|
||||||
|
...
|
@ -0,0 +1 @@
|
|||||||
|
website/** linguist-documentation
|
@ -0,0 +1,49 @@
|
|||||||
|
name: Deploy
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- "master"
|
||||||
|
paths:
|
||||||
|
- "website/**"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
if: github.repository == 'facebook/infer'
|
||||||
|
|
||||||
|
env:
|
||||||
|
working-directory: website
|
||||||
|
node-version: 14.x
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Use Node.js ${{ env.node-version }}
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: ${{ env.node-version }}
|
||||||
|
|
||||||
|
- name: Get yarn cache directory
|
||||||
|
id: yarn
|
||||||
|
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||||
|
|
||||||
|
- name: Restore yarn cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: ${{ steps.yarn.outputs.dir }}
|
||||||
|
key: ${{ runner.os }}-yarn-${{ hashFiles('website/yarn.lock') }}
|
||||||
|
|
||||||
|
- name: Install packages
|
||||||
|
working-directory: ${{ env.working-directory }}
|
||||||
|
run: yarn --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Deploy to GitHub Pages
|
||||||
|
working-directory: ${{ env.working-directory }}
|
||||||
|
run: |
|
||||||
|
git config --global user.email "${GITHUB_ACTOR}@users.noreply.github.com"
|
||||||
|
git config --global user.name "${GITHUB_ACTOR}"
|
||||||
|
echo "machine github.com login ${GITHUB_ACTOR} password ${{ secrets.GITHUB_TOKEN }}" > ~/.netrc
|
||||||
|
GIT_USER=${GITHUB_ACTOR} yarn deploy
|
@ -0,0 +1,189 @@
|
|||||||
|
name: Install
|
||||||
|
|
||||||
|
on:
|
||||||
|
- push
|
||||||
|
- pull_request
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
create-release:
|
||||||
|
name: Create release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
upload-url: ${{ steps.create-release.outputs.upload_url }}
|
||||||
|
steps:
|
||||||
|
- name: Create Release
|
||||||
|
id: create-release
|
||||||
|
if: startsWith(github.ref, 'refs/tags/v')
|
||||||
|
uses: actions/create-release@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
tag_name: ${{ github.ref }}
|
||||||
|
release_name: Infer version ${{ github.ref }}
|
||||||
|
draft: true
|
||||||
|
prerelease: false
|
||||||
|
body: |
|
||||||
|
BEFORE PUBLISHING CHECKLIST:
|
||||||
|
1. From the commit tagged on GitHub, create and push a new version of the website with "make new-website-version" (see website/README.md for how to test).
|
||||||
|
2. Consider deleting the oldest documentation version (see Docusaurus 2 documentation for details).
|
||||||
|
3. Fill in the changelog below to go on GitHub.
|
||||||
|
4. Download the release tarballs and test that the binaries works.
|
||||||
|
5. Fill in the shasums by running the command at the end of the release text.
|
||||||
|
--- PUBLISH GITHUB RELEASE HERE ---
|
||||||
|
6. At some point, copy the GitHub changelog to Changelog.md in the repo.
|
||||||
|
7. Tweet.
|
||||||
|
--- DELETE EVERYTHING ABOVE THIS LINE ---
|
||||||
|
|
||||||
|
This is a binary release of Infer for Linux and MacOS. To use it follow these [instructions](http://fbinfer.com/docs/getting-started).
|
||||||
|
|
||||||
|
- new feature 1
|
||||||
|
- new feature 2
|
||||||
|
|
||||||
|
The sha256 checksums of the tarballs are:
|
||||||
|
```
|
||||||
|
$ shasum -a 256 infer-*-v<VERSION GOES HERE>.tar.xz
|
||||||
|
DOWNLOAD BOTH TARBALLS AND PUT RESULT OF THE ABOVE COMMAND HERE BEFORE PUBLISHING
|
||||||
|
```
|
||||||
|
|
||||||
|
build:
|
||||||
|
name: Build Infer
|
||||||
|
needs: create-release
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os:
|
||||||
|
- macOS-latest
|
||||||
|
- ubuntu-latest
|
||||||
|
ocaml-version:
|
||||||
|
- 4.12.0
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install Required Apt Packages for Ubuntu
|
||||||
|
run: |
|
||||||
|
sudo apt install libmpfr-dev libsqlite3-dev ninja-build
|
||||||
|
sudo apt clean
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
|
||||||
|
- name: Install Required Brew Packages for MacOS
|
||||||
|
run: brew install automake jq ninja pkg-config lzlib
|
||||||
|
if: runner.os == 'macOS'
|
||||||
|
|
||||||
|
- name: Compute hash of clang installation
|
||||||
|
id: clang-hash
|
||||||
|
run: |
|
||||||
|
echo "::set-output name=value::$(./facebook-clang-plugins/clang/setup.sh --clang-hash)"
|
||||||
|
|
||||||
|
- name: Attempt to get clang from the cache
|
||||||
|
id: cache-clang
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: facebook-clang-plugins/clang/install
|
||||||
|
key: clang-${{ runner.os }}-${{ steps.clang-hash.outputs.value }}
|
||||||
|
|
||||||
|
- name: Record that the clang cache was hit
|
||||||
|
if: steps.cache-clang.outputs.cache-hit == 'true'
|
||||||
|
run: ./facebook-clang-plugins/clang/setup.sh --only-record-install
|
||||||
|
|
||||||
|
- name: Build clang on cache misses
|
||||||
|
if: steps.cache-clang.outputs.cache-hit != 'true'
|
||||||
|
run: |
|
||||||
|
./facebook-clang-plugins/clang/src/prepare_clang_src.sh
|
||||||
|
./facebook-clang-plugins/clang/setup.sh --ninja --sequential-link
|
||||||
|
|
||||||
|
- name: Attempt to get opam tree from the cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: ~/.opam
|
||||||
|
key: opam-${{ runner.os }}-${{ hashFiles('opam/infer.opam.locked') }}
|
||||||
|
|
||||||
|
- name: Use OCaml ${{ matrix.ocaml-version }}
|
||||||
|
uses: avsm/setup-ocaml@v1
|
||||||
|
with:
|
||||||
|
ocaml-version: ${{ matrix.ocaml-version }}
|
||||||
|
|
||||||
|
- run: ./build-infer.sh --yes all
|
||||||
|
|
||||||
|
- run: make install BUILD_MODE=opt
|
||||||
|
if: runner.os == 'macOS'
|
||||||
|
|
||||||
|
- run: |
|
||||||
|
sudo make install BUILD_MODE=opt
|
||||||
|
# restore permissions after root build
|
||||||
|
sudo chown $USER: -R .
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
|
||||||
|
- name: Test infer
|
||||||
|
run: |
|
||||||
|
eval $(opam env)
|
||||||
|
|
||||||
|
{
|
||||||
|
echo 'class FailingTest {'
|
||||||
|
echo ' String mayReturnNull(int i) {'
|
||||||
|
echo ' if (i > 0) {'
|
||||||
|
echo ' return "Hello, Infer!";'
|
||||||
|
echo ' }'
|
||||||
|
echo ' return null;'
|
||||||
|
echo ' }'
|
||||||
|
echo ' int mayCauseNPE() {'
|
||||||
|
echo ' String s = mayReturnNull(0);'
|
||||||
|
echo ' return s.length();'
|
||||||
|
echo ' }'
|
||||||
|
echo '}'
|
||||||
|
} > FailingTest.java
|
||||||
|
|
||||||
|
{
|
||||||
|
echo " class PassingTest {"
|
||||||
|
echo " String mayReturnNull(int i) {"
|
||||||
|
echo " if (i > 0) {"
|
||||||
|
echo ' return "Hello, Infer!";'
|
||||||
|
echo " }"
|
||||||
|
echo " return null;"
|
||||||
|
echo " }"
|
||||||
|
echo " int mayCauseNPE() {"
|
||||||
|
echo " String s = mayReturnNull(0);"
|
||||||
|
echo " return s == null ? 0 : s.length();"
|
||||||
|
echo " }"
|
||||||
|
echo " }"
|
||||||
|
} > PassingTest.java
|
||||||
|
|
||||||
|
# first command should exit with status 2
|
||||||
|
infer --fail-on-issue -P -- javac FailingTest.java || if [[ $? -ne 2 ]]; then exit 1; fi
|
||||||
|
infer --fail-on-issue -P -- javac PassingTest.java
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "#include <stdio.h>"
|
||||||
|
echo "int main()"
|
||||||
|
echo "{ int *s = NULL; *s = 42; return 0; } "
|
||||||
|
} > FailingTest.c
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "#include <stdio.h>"
|
||||||
|
echo "int main()"
|
||||||
|
echo "{ int *s = NULL; if (s != NULL) { *s = 42; } return 0; }"
|
||||||
|
} > PassingTest.c
|
||||||
|
|
||||||
|
# first command should exit with status 2
|
||||||
|
infer --fail-on-issue -P -- clang -c FailingTest.c || if [[ $? -ne 2 ]]; then exit 1; fi
|
||||||
|
infer --fail-on-issue -P -- clang -c PassingTest.c
|
||||||
|
|
||||||
|
- name: Build release tarball
|
||||||
|
id: build-release
|
||||||
|
if: startsWith(github.ref, 'refs/tags/v')
|
||||||
|
run: |
|
||||||
|
./scripts/create_binary_release.sh "$(echo '${{ github.ref }}' | rev | cut -d / -f 1 | rev)"
|
||||||
|
|
||||||
|
- name: Upload Release Asset
|
||||||
|
if: startsWith(github.ref, 'refs/tags/v')
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ needs.create-release.outputs.upload-url }}
|
||||||
|
asset_path: ${{ steps.build-release.outputs.tarball-path }}
|
||||||
|
asset_name: ${{ steps.build-release.outputs.tarball-path }}
|
||||||
|
asset_content_type: application/x-gtar
|
@ -0,0 +1,216 @@
|
|||||||
|
# Generated files #
|
||||||
|
###################
|
||||||
|
*.pyc
|
||||||
|
*.specs
|
||||||
|
*.cm*
|
||||||
|
*.o
|
||||||
|
*~
|
||||||
|
*.swp
|
||||||
|
*.annot
|
||||||
|
*.class
|
||||||
|
*.log
|
||||||
|
*.orig
|
||||||
|
*.rej
|
||||||
|
.#*
|
||||||
|
|
||||||
|
# generated by build and tests
|
||||||
|
/_build
|
||||||
|
/_build_logs
|
||||||
|
/infer/lib/erlang/infer_parse_transform/_build
|
||||||
|
/infer/tests/codetoanalyze/java/*/codetoanalyze
|
||||||
|
_build_infer
|
||||||
|
*.exp.test*
|
||||||
|
*.dot.test
|
||||||
|
*.test.dot
|
||||||
|
*.test.txt
|
||||||
|
duplicates.txt
|
||||||
|
*.ast.sh
|
||||||
|
*.ast.bdump
|
||||||
|
*.ast.biniou
|
||||||
|
/infer/tests/build_systems/buck_flavors_deterministic/capture_hash-*.sha
|
||||||
|
/infer/tests/build_systems/buck_flavors_diff/src/hello.c
|
||||||
|
/infer/tests/build_systems/buck_clang_test_determinator/diff.mod.test
|
||||||
|
/infer/tests/build_systems/buck_export_changed_functions/diff.mod.test
|
||||||
|
/infer/tests/build_systems/clang_compilation_db_escaped/compile_commands.json
|
||||||
|
/infer/tests/build_systems/clang_compilation_db_relpath/compile_commands.json
|
||||||
|
/infer/tests/build_systems/clang_test_determinator/*.test
|
||||||
|
/infer/tests/build_systems/export_changed_functions/*.test
|
||||||
|
/infer/tests/build_systems/clang_with_MD_flag/hello.d
|
||||||
|
/infer/tests/build_systems/codetoanalyze/mvn/**/target/
|
||||||
|
/infer/tests/build_systems/codetoanalyze/ndk-build/hello_app/libs/
|
||||||
|
/infer/tests/build_systems/codetoanalyze/ndk-build/hello_app/obj/
|
||||||
|
/infer/tests/build_systems/codetoanalyze/path with spaces/
|
||||||
|
/infer/tests/build_systems/codetoanalyze/rebar3/erl_hi/_build
|
||||||
|
/infer/tests/build_systems/codetoanalyze/utf8_*n_pwd
|
||||||
|
/infer/tests/build_systems/codetoanalyze/xcodebuild/simple_app/app_built
|
||||||
|
/infer/tests/build_systems/codetoanalyze/xcodebuild/simple_app/build/
|
||||||
|
/infer/tests/build_systems/diff/src
|
||||||
|
/infer/tests/build_systems/diff_*/src
|
||||||
|
/infer/tests/build_systems/differential_*/**/*.class
|
||||||
|
/infer/tests/build_systems/differential_*/**/Diff*.java
|
||||||
|
/infer/tests/build_systems/differential_*/**/Diff*.m
|
||||||
|
/infer/tests/build_systems/fb_differential_*/**/Diff*.java
|
||||||
|
/infer/tests/build_systems/fb_differential_*/**/Diff*.m
|
||||||
|
/infer/tests/build_systems/incremental_analysis_remove_file/src
|
||||||
|
/infer/tests/build_systems/incremental_analysis_cost_change/src
|
||||||
|
/infer/tests/build_systems/incremental_analysis_add_procedure/src
|
||||||
|
/infer/tests/build_systems/java_test_determinator/*.test
|
||||||
|
/infer/tests/build_systems/java_source_parser/*.test
|
||||||
|
/infer/tests/codetoanalyze/dotnet/*/*.json
|
||||||
|
/infer/tests/codetoanalyze/erlang/**/_build
|
||||||
|
/_release
|
||||||
|
/infer-source
|
||||||
|
|
||||||
|
# Docusaurus
|
||||||
|
/website/.docusaurus/
|
||||||
|
/website/node_modules
|
||||||
|
/website/build/
|
||||||
|
|
||||||
|
# generated by oUnit
|
||||||
|
/oUnit-all.cache
|
||||||
|
|
||||||
|
# autoconf-generated stuff
|
||||||
|
/acinclude.m4
|
||||||
|
/aclocal.m4
|
||||||
|
/autom4te.cache
|
||||||
|
/config.status
|
||||||
|
/m4/__GENERATED__*.m4
|
||||||
|
/configure
|
||||||
|
/Makefile.autoconf
|
||||||
|
/.buckversion
|
||||||
|
/.buck-java11
|
||||||
|
/.buckjavaversion
|
||||||
|
/*/.gitignore
|
||||||
|
/*/*/.gitignore
|
||||||
|
|
||||||
|
# IntelliJ files
|
||||||
|
/scripts/.idea/
|
||||||
|
/infer/tests/.idea/dictionaries
|
||||||
|
/infer/tests/.idea/inspectionProfiles
|
||||||
|
/infer/tests/.idea/tasks.xml
|
||||||
|
/infer/tests/.idea/uiDesigner.xml
|
||||||
|
/infer/tests/.idea/workspace.xml
|
||||||
|
/infer/tests/.idea/runConfigurations
|
||||||
|
/infer/tests/.idea/copyright/profiles_settings.xml
|
||||||
|
|
||||||
|
# VS code
|
||||||
|
.vscode/
|
||||||
|
.lsp-buck-out/
|
||||||
|
.lsp.buckd/
|
||||||
|
|
||||||
|
# Eclipse settings files
|
||||||
|
ocaml.prefs
|
||||||
|
/infer/.paths
|
||||||
|
/infer/src/.paths
|
||||||
|
org.eclipse.core.resources.prefs
|
||||||
|
|
||||||
|
# Arcanist
|
||||||
|
/arcanist/.phutil_module_cache
|
||||||
|
|
||||||
|
# MacOS generated files
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Directories and files generated by Infer
|
||||||
|
infer-sources.tar.gz
|
||||||
|
infer-osx-*.tar.xz
|
||||||
|
infer-linux64-*.tar.xz
|
||||||
|
infer-out*
|
||||||
|
|
||||||
|
# Directories generated by buck
|
||||||
|
buck-out/
|
||||||
|
.buckd/
|
||||||
|
|
||||||
|
#other
|
||||||
|
/infer/man/man1/*.1
|
||||||
|
/infer/man/man1/*.1.gz
|
||||||
|
|
||||||
|
/infer/src/base/Version.ml
|
||||||
|
/infer/models/java/models/
|
||||||
|
/infer/models/models.jar
|
||||||
|
/infer/lib/java/models.jar
|
||||||
|
/infer/lib/models.sql
|
||||||
|
/infer/models/java/bootclasspath
|
||||||
|
/infer/models/c/out/
|
||||||
|
/infer/models/cpp/out/
|
||||||
|
/infer/models/objc/out/
|
||||||
|
/infer/lib/specs/c_models
|
||||||
|
/infer/lib/specs/clang_models
|
||||||
|
/infer/lib/specs/cpp_models
|
||||||
|
/infer/lib/specs/objc_models
|
||||||
|
/infer/lib/specs/clean_models
|
||||||
|
/infer/etc/clang_ast.dict
|
||||||
|
/infer/src/toplevel.mlpack
|
||||||
|
|
||||||
|
/external_repo
|
||||||
|
|
||||||
|
# atdgen generated files
|
||||||
|
/infer/src/atd/*_j.ml
|
||||||
|
/infer/src/atd/*_j.mli
|
||||||
|
/infer/src/atd/*_t.ml
|
||||||
|
/infer/src/atd/*_t.mli
|
||||||
|
/infer/src/atd/clang_*.ml
|
||||||
|
/infer/src/atd/clang_*.mli
|
||||||
|
|
||||||
|
# intelliJ files
|
||||||
|
/infer/src/backend/.projectSettings
|
||||||
|
|
||||||
|
/infer/annotations/annot_classes/
|
||||||
|
/infer/annotations/annotations.jar
|
||||||
|
/infer/annotations/annotations-src.jar
|
||||||
|
infer/src/.project
|
||||||
|
/dependencies/ocamldot/ocamldot
|
||||||
|
/dependencies/ocamldot/ocamldot.ml
|
||||||
|
/infer/src/mod_dep.dot
|
||||||
|
/infer/src/mod_dep.pdf
|
||||||
|
|
||||||
|
# generated by Maven
|
||||||
|
/infer/annotations/target
|
||||||
|
|
||||||
|
# generated by Erlang/Rebar3
|
||||||
|
*.beam
|
||||||
|
*.plt
|
||||||
|
*.swo
|
||||||
|
.erlang.cookie
|
||||||
|
.eunit
|
||||||
|
.rebar
|
||||||
|
.rebar3
|
||||||
|
ebin
|
||||||
|
erl_crash.dump
|
||||||
|
rebar.lock
|
||||||
|
rebar3.crashdump
|
||||||
|
|
||||||
|
|
||||||
|
# dune
|
||||||
|
/infer/_build
|
||||||
|
/infer/dune-workspace
|
||||||
|
/infer/src/dune.common
|
||||||
|
/infer/src/dune
|
||||||
|
/infer/src/al/dune
|
||||||
|
/infer/src/clang/dune
|
||||||
|
/infer/src/integration/dune
|
||||||
|
/infer/src/java/dune
|
||||||
|
/infer/src/nullsafe/unit/dune
|
||||||
|
/infer/src/opensource/dune
|
||||||
|
/infer/src/unit/dune
|
||||||
|
.merlin
|
||||||
|
|
||||||
|
# generated when looking for dead code
|
||||||
|
/infer/src/deadcode/.depend
|
||||||
|
/infer/src/deadcode/all_ml_files
|
||||||
|
/infer/src/deadcode/all_ml_files_copied
|
||||||
|
/infer/src/deadcode/all_mli_files
|
||||||
|
/infer/src/deadcode/all_mli_files_copied
|
||||||
|
/infer/src/deadcode/*.ml
|
||||||
|
/infer/src/deadcode/*.mli
|
||||||
|
/infer/src/deadcode/dune
|
||||||
|
_opam
|
||||||
|
_coverage
|
||||||
|
|
||||||
|
# facebook-clang-plugins
|
||||||
|
/facebook-clang-plugins/clang-ocaml/.depend
|
||||||
|
/facebook-clang-plugins/clang-ocaml/build
|
||||||
|
/facebook-clang-plugins/clang/install
|
||||||
|
/facebook-clang-plugins/clang/installed.version
|
||||||
|
/facebook-clang-plugins/clang/src/download
|
||||||
|
/facebook-clang-plugins/libtooling/build
|
||||||
|
/facebook-clang-plugins/xcode/*
|
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"force-delete-results-dir": true,
|
||||||
|
"siof-safe-methods": ["getGlobalNonPODAllowListed", "allow_listed::getGlobalNonPOD",
|
||||||
|
"allow_listed::TemplatedObject::getGlobalNonPOD"],
|
||||||
|
"skip-translation": [
|
||||||
|
{
|
||||||
|
"language": "Java",
|
||||||
|
"source_contains": "_SHOULD_BE_SKIPPED_"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
infer/src/.ocamlformat
|
@ -0,0 +1,230 @@
|
|||||||
|
# Contribution Guidelines
|
||||||
|
|
||||||
|
|
||||||
|
## Reporting Issues
|
||||||
|
|
||||||
|
If you encounter a problem when using infer or if you have any questions, please open a
|
||||||
|
[GitHub issue](https://github.com/facebook/infer/issues/).
|
||||||
|
|
||||||
|
## Hacking on the Code
|
||||||
|
|
||||||
|
We welcome contributions via [pull requests on GitHub](https://github.com/facebook/infer/pulls).
|
||||||
|
|
||||||
|
### Development Dependencies
|
||||||
|
|
||||||
|
You'll want to install a few more dependencies to comfortably hack on the infer codebase. Simply
|
||||||
|
run:
|
||||||
|
```sh
|
||||||
|
make devsetup
|
||||||
|
```
|
||||||
|
|
||||||
|
### Building Infer for Development
|
||||||
|
|
||||||
|
- The default build mode ("dev") makes all build warnings *fatal*. If you want the build to ignore
|
||||||
|
warnings, for example to be able to test an infer executable before polishing the code to remove
|
||||||
|
warnings, you can build in "dev-noerror" mode with `make BUILD_MODE=dev-noerror`.
|
||||||
|
|
||||||
|
- Faster edit/build cycle when working on OCaml code inside infer/src/: build inside infer/src/
|
||||||
|
(skips building the models after infer has been built), and build only what is needed for type
|
||||||
|
checking with `make -j -C infer/src check`. You need to have run `make -j` at some point before.
|
||||||
|
|
||||||
|
- Alternatively, if you want to test your changes on a small example, build in bytecode mode:
|
||||||
|
`make -j -C infer/src byte`.
|
||||||
|
|
||||||
|
- In general, `make` commands from the root of the repository make sure that dependencies are in a
|
||||||
|
consistent and up-to-date state (e.g., they rebuild infer and the models before running steps that
|
||||||
|
use infer), while running `make` commands from within subdirectories generally assumes that
|
||||||
|
dependencies are already up-to-date.
|
||||||
|
|
||||||
|
For instance, running `make direct_java_biabduction_test` will rebuild infer and the models if
|
||||||
|
necessary before running the test, but running `make -C infer/tests/codetoanalyze/java/biabduction/ test`
|
||||||
|
will just execute the test.
|
||||||
|
|
||||||
|
|
||||||
|
### Debugging OCaml Code
|
||||||
|
|
||||||
|
- Printf-debug using `Logging.debug_dev`. It comes with a warning so
|
||||||
|
that you don't accidentally push code with calls to `debug_dev` to
|
||||||
|
the repo.
|
||||||
|
|
||||||
|
- Browse the documentation of OCaml modules in your browser with `make doc`
|
||||||
|
|
||||||
|
- When using `ocamldebug`, and in particular when setting break points
|
||||||
|
with `break @ <module> <line>` don't forget that an infer module `M`
|
||||||
|
is in reality called `InferModules__M`, or `InferBase__M`, or
|
||||||
|
... See the html documentation of the OCaml modules from `make doc`
|
||||||
|
if you're unsure of a module name.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ ledit ocamldebug infer/bin/infer.bc.exe
|
||||||
|
(ocd) break @ InferModules__InferAnalyze 100
|
||||||
|
Breakpoint 1 at 9409684: file backend/InferAnalyze.ml, line 99, characters 18-78
|
||||||
|
```
|
||||||
|
|
||||||
|
- To test the infer OCaml code you can use the OCaml toplevel. To
|
||||||
|
build the OCaml toplevel with the infer modules pre-loaded, run
|
||||||
|
`make toplevel` and follow the instructions.
|
||||||
|
|
||||||
|
To pass infer options to the toplevel, use `INFER_ARGS`, for
|
||||||
|
instance: `INFER_ARGS=--debug^-o^infer-out-foo`.
|
||||||
|
|
||||||
|
Many operations require the results directory and database to be
|
||||||
|
initialized with `ResultsDir.assert_results_dir ""`.
|
||||||
|
|
||||||
|
|
||||||
|
## Contributor License Agreement
|
||||||
|
|
||||||
|
We require contributors to sign our Contributor License Agreement. In
|
||||||
|
order for us to review and merge your code, please sign up at
|
||||||
|
https://code.facebook.com/cla. If you have any questions, please drop
|
||||||
|
us a line at cla@fb.com.
|
||||||
|
|
||||||
|
You are also expected to follow the [Code of Conduct](CODE_OF_CONDUCT.md), so please read that if you are a new contributor.
|
||||||
|
|
||||||
|
Thanks!
|
||||||
|
|
||||||
|
## Coding Style
|
||||||
|
|
||||||
|
### All Languages
|
||||||
|
|
||||||
|
- Indent with spaces, not tabs.
|
||||||
|
|
||||||
|
- Line width limit is 100 characters.
|
||||||
|
|
||||||
|
- In general, follow the style of surrounding code.
|
||||||
|
|
||||||
|
### OCaml
|
||||||
|
|
||||||
|
- The module IStd (infer/src/istd/IStd.ml) is automatically opened in every file. Beware that this
|
||||||
|
can cause weird errors such as:
|
||||||
|
```
|
||||||
|
$ pwd
|
||||||
|
/somewhere/infer/infer/src
|
||||||
|
$ cat base/toto.ml
|
||||||
|
let b = List.mem true [true; false]
|
||||||
|
$ make
|
||||||
|
[...]
|
||||||
|
File "base/toto.ml", line 1, characters 17-21:
|
||||||
|
Error: This variant expression is expected to have type 'a list
|
||||||
|
The constructor true does not belong to type list
|
||||||
|
```
|
||||||
|
|
||||||
|
- All modules open `IStd` using `open! IStd`. This is to make that fact more explicit (there's also
|
||||||
|
the compilation flag mentioned above), and also it helps merlin find the right types. In
|
||||||
|
particular this also opens `Core.Std`.
|
||||||
|
|
||||||
|
- Do not add anything to `IStd` unless you have a compelling reason to do so, for instance if you
|
||||||
|
find some utility function is missing and is not provided by
|
||||||
|
[`Core`](https://ocaml.janestreet.com/ocaml-core/latest/doc/core/).
|
||||||
|
|
||||||
|
- Polymorphic equality is disabled; use type-specific equality instead, even for primitive types
|
||||||
|
(e.g., `Int.equal`). However, if your module uses a lot of polymorphic variants with no arguments
|
||||||
|
you may safely `open PolyVariantEqual`.
|
||||||
|
|
||||||
|
If you try and use polymorphic equality `=` in your code you will get a compilation error, such as:
|
||||||
|
```
|
||||||
|
Error: This expression has type int but an expression was expected of type
|
||||||
|
[ `no_polymorphic_compare ]
|
||||||
|
```
|
||||||
|
|
||||||
|
- Alias and use `module L = Logging` for all your logging needs. Refer to its API in Logging.mli for
|
||||||
|
documentation.
|
||||||
|
|
||||||
|
- Check that your code compiles without warnings with `make -j test_build` (this also runs as part
|
||||||
|
of `make test`).
|
||||||
|
|
||||||
|
- Apart from `IStd` and `PolyVariantEqual`, refrain from globally `open`ing modules. Using
|
||||||
|
local open instead when it improves readability: `let open MyModule in ...`.
|
||||||
|
|
||||||
|
- Avoid the use of module aliases, except for the following commonly-aliased modules. Use
|
||||||
|
module aliases consistently (e.g., do not alias `L` to a module other than `Logging`).
|
||||||
|
```OCaml
|
||||||
|
module CLOpt = CommandLineOption
|
||||||
|
module F = Format
|
||||||
|
module L = Logging
|
||||||
|
module MF = MarkupFormatter
|
||||||
|
```
|
||||||
|
|
||||||
|
- Use `[@@deriving compare]` to write comparison functions whenever possible. Watch out for
|
||||||
|
[this issue](https://github.com/ocaml-ppx/ppx_deriving/issues/116) when writing
|
||||||
|
`type nonrec t = t [@@deriving compare]`.
|
||||||
|
|
||||||
|
- Use `let equal_foo = [%compare.equal : foo]` to write equality functions whenever possible.
|
||||||
|
|
||||||
|
- Use named arguments whenever the purpose of the argument is not immediately obvious. In
|
||||||
|
particular, use named arguments for boolean and integer parameters unless the name of the function
|
||||||
|
mentions them explicitly. Also use named arguments to disambiguate between several arguments of
|
||||||
|
the same type.
|
||||||
|
|
||||||
|
- Use named arguments for functions taken as argument; it is common to name a function argument
|
||||||
|
`f`. For instance: `List.map : 'a list -> f:('a -> 'b) -> 'b list`.
|
||||||
|
|
||||||
|
- In modules defining a type `t`, functions that take an argument of that type should generally have
|
||||||
|
that argument come first, except for for optional arguments: `val f : ?optional:bool -> t -> ...`.
|
||||||
|
|
||||||
|
- Use the `_hum` suffix to flag functions that output human-readable strings.
|
||||||
|
|
||||||
|
- Format code with [ocamlformat](https://github.com/ocaml-ppx/ocamlformat).
|
||||||
|
|
||||||
|
### C/C++/Objective-C
|
||||||
|
|
||||||
|
Follow `clang-format` (see ".clang-format" at the root of the repository).
|
||||||
|
|
||||||
|
## Testing your Changes
|
||||||
|
|
||||||
|
- Make sure infer builds: `make -j test_build`. Refer to the [installation
|
||||||
|
document](https://github.com/facebook/infer/blob/master/INSTALL.md) for details.
|
||||||
|
|
||||||
|
- Run the tests: `make -j 4 test` (adjust 4 to the number of cores available of your machine). The
|
||||||
|
tests (almost) all consist of the same three ingredients:
|
||||||
|
1. Some source code to run infer on.
|
||||||
|
2. An "issues.exp" file where each line represents one item of output of the test. For most tests,
|
||||||
|
one line is one issue reported by infer.
|
||||||
|
3. A `Makefile` that orchestrates the test, for instance running infer on the source code and
|
||||||
|
comparing the results with issues.exp using `diff`.
|
||||||
|
|
||||||
|
- If your changes modified some of the expected outputs and if the changes make sense, you can
|
||||||
|
update the expected test results by running `make test-replace`.
|
||||||
|
|
||||||
|
- If relevant, add a test for your change.
|
||||||
|
|
||||||
|
- To add a test that infer finds (or does not find) a particular issue, add your test in
|
||||||
|
"infer/tests/codetoanalyze/{language}/{analyzer}/". Look at the `Makefile` in that directory and
|
||||||
|
make sure it runs your test. "{analyzer}" is often an infer analyzer (as in
|
||||||
|
`infer -a {analyzer}`), with some special cases:
|
||||||
|
- "errors" is "infer"
|
||||||
|
- "frontend" is a mode where the expected output is the result of the translation of the program
|
||||||
|
by infer's clang frontend into infer's intermediate representation.
|
||||||
|
|
||||||
|
Name the procedures in your test following these conventions:
|
||||||
|
- Test procedures where the analyzer should report an error should end with the suffix `Bad`.
|
||||||
|
- Test procedures where the analyzer should not report an error should end with the suffix `Ok`.
|
||||||
|
- Test procedures documenting current limitations of the analyzer should have the prefix `FP_`
|
||||||
|
(for "false positive") or `FN_` (for "false negative") and a comment explaining why the analyzer
|
||||||
|
gets the wrong answer.
|
||||||
|
|
||||||
|
|
||||||
|
- To add a test that a certain build system integration or a command-line option works in a certain
|
||||||
|
way, add a test in "infer/tests/build_systems/".
|
||||||
|
|
||||||
|
- If you created a new Makefile for your test, add it to the root "Makefile", either to the
|
||||||
|
`DIRECT_TESTS` (first case) or to the `BUILD_SYSTEMS_TESTS` variable (second case). Gate the
|
||||||
|
test appropriately if it depends on Java or Clang or Xcode (see how other tests do it).
|
||||||
|
|
||||||
|
- It can be useful to look at the debug HTML output of infer to see the detail of the symbolic
|
||||||
|
execution. For instance:
|
||||||
|
```sh
|
||||||
|
$ infer --debug -- clang -c examples/hello.c
|
||||||
|
$ firefox infer-out/captured/hello.c.*.html
|
||||||
|
```
|
||||||
|
|
||||||
|
## Updating infer.opam and infer.opam.locked
|
||||||
|
|
||||||
|
tl; dr: Run `make opam/infer.opam.locked`.
|
||||||
|
|
||||||
|
infer.opam.locked records fixed versions of the opam dependencies known to work with infer and to respect
|
||||||
|
the constraints in opam. This prevents unpredictable breakages of infer or its dependencies,
|
||||||
|
especially for infer releases, for which it is more difficult to change their package constraints
|
||||||
|
after the fact.
|
||||||
|
|
||||||
|
To add an opam package or update its version constraints, edit 'infer.opam' then run `make infer.opam.locked`.
|
@ -0,0 +1,3 @@
|
|||||||
|
Kihong Heo <khheo@ropas.snu.ac.kr>
|
||||||
|
Sungkeun Cho <skcho@ropas.snu.ac.kr>
|
||||||
|
Kwangkeun Yi <kwang@ropas.snu.ac.kr>
|
@ -0,0 +1,7 @@
|
|||||||
|
#Files in infer/bin/
|
||||||
|
|
||||||
|
## Top-level commands
|
||||||
|
|
||||||
|
*infer* : Main command to run Infer. Check out the docs for instructions on how to use it.
|
||||||
|
|
||||||
|
*infer-<command>* : Infer subcommands. Running `infer-<command> [options]` is the same as running `infer <command> [options]`.
|
@ -0,0 +1,111 @@
|
|||||||
|
# How to install Infer from source
|
||||||
|
|
||||||
|
## Binary versions
|
||||||
|
|
||||||
|
We provide a binary release of Infer. We encourage you to use this
|
||||||
|
release as compiling infer's dependencies is time-consuming. Follow
|
||||||
|
the instructions in our [Getting
|
||||||
|
Started](http://fbinfer.com/docs/getting-started/#get-infer)
|
||||||
|
page to install Infer.
|
||||||
|
|
||||||
|
|
||||||
|
## Infer dependencies for MacOSX
|
||||||
|
|
||||||
|
Here are the prerequisites to be able to compile Infer on MacOSX. This
|
||||||
|
is required to compile everything from source.
|
||||||
|
|
||||||
|
- opam >= 2.0.0 (instructions [here](https://opam.ocaml.org/doc/Install.html#OSX))
|
||||||
|
- sqlite
|
||||||
|
- pkg-config
|
||||||
|
- Java (only needed for the Java analysis)
|
||||||
|
- CMake (only needed for the C/Objective-C analysis)
|
||||||
|
- Ninja (optional, if you wish to use sequential linking when building the
|
||||||
|
C/Objective-C analysis)
|
||||||
|
- clang in Xcode command line tools. You can install them with the command
|
||||||
|
`xcode-select --install` (only needed for the C/Objective-C analysis)
|
||||||
|
- Xcode >= 6.1 (only needed for the C/Objective-C analysis)
|
||||||
|
- autoconf >= 2.63 and automake >= 1.11.1 (if building from git)
|
||||||
|
- gmp
|
||||||
|
- mpfr
|
||||||
|
|
||||||
|
You can install some of these dependencies using
|
||||||
|
[Homebrew](http://brew.sh/):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
brew install autoconf automake cmake opam pkg-config sqlite gmp mpfr
|
||||||
|
brew cask install java
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Infer dependencies for Linux
|
||||||
|
|
||||||
|
Here are the prerequisites to be able to compile Infer on Linux. This
|
||||||
|
is required to compile everything from source.
|
||||||
|
|
||||||
|
- opam >= 2.0.0
|
||||||
|
- pkg-config
|
||||||
|
- Java (only needed for the Java analysis)
|
||||||
|
- gcc >= 5.X or clang >= 3.4 (only needed for the C/Objective-C analysis)
|
||||||
|
- autoconf >= 2.63 and automake >= 1.11.1 (if building from git)
|
||||||
|
- CMake (only needed for the C/Objective-C analysis)
|
||||||
|
- Ninja (optional, if you wish to use sequential linking when building the
|
||||||
|
C/Objective-C analysis)
|
||||||
|
|
||||||
|
See also the distro-specific instructions for Ubuntu and Debian below.
|
||||||
|
|
||||||
|
|
||||||
|
## Install Infer from source
|
||||||
|
|
||||||
|
Run the following commands to get Infer up and running:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Checkout Infer
|
||||||
|
git clone https://github.com/facebook/infer.git
|
||||||
|
cd infer
|
||||||
|
# Compile Infer
|
||||||
|
./build-infer.sh java
|
||||||
|
# install Infer system-wide...
|
||||||
|
sudo make install
|
||||||
|
# ...or, alternatively, install Infer into your PATH
|
||||||
|
export PATH=`pwd`/infer/bin:$PATH
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace `./build-infer.sh java` with `./build-infer.sh clang` to build
|
||||||
|
the C and Objective-C analyzer from source. Beware that this command
|
||||||
|
may take a really long time because it will compile a custom version
|
||||||
|
of clang. This custom version is used by Infer to parse C and
|
||||||
|
Objective-C source code.
|
||||||
|
|
||||||
|
See `./build-infer.sh --help` for more options, eg `./build-infer.sh`
|
||||||
|
on its own will build the analyzers for both Java and C/ObjC.
|
||||||
|
|
||||||
|
|
||||||
|
## Install Infer from source without opam
|
||||||
|
|
||||||
|
If for some reason you prefer to install Infer's OCaml dependencies by
|
||||||
|
some means other than opam, you can still compile Infer by running:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./autogen.sh
|
||||||
|
./configure # Disable Java or C/C++/ObjC analyzers with --disable-java-analyzers or --disable-c-analyzers
|
||||||
|
make
|
||||||
|
# install Infer system-wide...
|
||||||
|
sudo make install
|
||||||
|
# ...or, alternatively, install Infer into your PATH
|
||||||
|
export PATH=`pwd`/infer/bin:$PATH
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## How to install the dependencies on Linux
|
||||||
|
|
||||||
|
See the Dockerfile in docker/ for inspiration. It includes the
|
||||||
|
dependencies needed to build Infer on Debian 9 (stretch).
|
||||||
|
|
||||||
|
|
||||||
|
### Setting up opam
|
||||||
|
|
||||||
|
Get opam from your distribution, or from the
|
||||||
|
[opam website](http://opam.ocaml.org/doc/Install.html#Binarydistribution).
|
||||||
|
|
||||||
|
The OCaml dependencies needed by Infer are automatically handled by
|
||||||
|
opam when running `./build-infer.sh`.
|
@ -0,0 +1,10 @@
|
|||||||
|
Please make sure your issue is not addressed in the [FAQ](https://fbinfer.com/docs/support#troubleshooting).
|
||||||
|
|
||||||
|
Please include the following information:
|
||||||
|
- [ ] The version of infer from `infer --version`.
|
||||||
|
- [ ] Your operating system and version, for example "Debian 9", "MacOS High Sierra", whether you are using Docker, etc.
|
||||||
|
- [ ] Which command you ran, for example `infer -- make`.
|
||||||
|
- [ ] The full output in a paste, for instance a [gist](https://gist.github.com/).
|
||||||
|
- [ ] If possible, a minimal example to reproduce your problem (for instance, some code where
|
||||||
|
infer reports incorrectly, together with the way you run infer to reproduce the incorrect
|
||||||
|
report).
|
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
@ -0,0 +1,101 @@
|
|||||||
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
#
|
||||||
|
# This source code is licensed under the MIT license found in the
|
||||||
|
# LICENSE file in the root directory of this source tree.
|
||||||
|
|
||||||
|
@SET_MAKE@
|
||||||
|
|
||||||
|
ANT = @ANT@
|
||||||
|
ATDGEN = @ATDGEN@
|
||||||
|
bindir = @bindir@
|
||||||
|
BUCK = @BUCK@
|
||||||
|
BUILD_C_ANALYZERS = @BUILD_C_ANALYZERS@
|
||||||
|
BUILD_ERLANG_ANALYZERS = @BUILD_ERLANG_ANALYZERS@
|
||||||
|
BUILD_JAVA_ANALYZERS = @BUILD_JAVA_ANALYZERS@
|
||||||
|
BUILD_PLATFORM = @BUILD_PLATFORM@
|
||||||
|
CAML_LD_LIBRARY_PATH = @CAML_LD_LIBRARY_PATH@
|
||||||
|
CC = @CC@
|
||||||
|
CFLAGS = @CFLAGS@
|
||||||
|
CLANG_INCLUDES = @CLANG_INCLUDES@
|
||||||
|
CLANG_PREFIX = @CLANG_PREFIX@
|
||||||
|
CMAKE = @CMAKE@
|
||||||
|
CPATH = @CPATH@
|
||||||
|
CPP = @CPP@
|
||||||
|
CXX = @CXX@
|
||||||
|
CXXFLAGS = @CXXFLAGS@
|
||||||
|
# this is useless but autoconf is picky...
|
||||||
|
datarootdir = @datarootdir@
|
||||||
|
EMACS = @EMACS@
|
||||||
|
ENABLE_OCAMLOPT_CUSTOM_CC = @ENABLE_OCAMLOPT_CUSTOM_CC@
|
||||||
|
ENABLE_OCAML_BINANNOT = @ENABLE_OCAML_BINANNOT@
|
||||||
|
exec_prefix = @exec_prefix@
|
||||||
|
GNU_SED = @GNU_SED@
|
||||||
|
HAS_OBJC = @HAS_OBJC@
|
||||||
|
INFER_MAJOR = @INFER_MAJOR@
|
||||||
|
INFER_MAN_LAST_MODIFIED = @INFER_MAN_LAST_MODIFIED@
|
||||||
|
INFER_MINOR = @INFER_MINOR@
|
||||||
|
INFER_PATCH = @INFER_PATCH@
|
||||||
|
INSTALL = @INSTALL@
|
||||||
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
|
INSTALL_NAME_TOOL = @INSTALL_NAME_TOOL@
|
||||||
|
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||||
|
IS_FACEBOOK_TREE = @IS_FACEBOOK_TREE@
|
||||||
|
IS_RELEASE_TREE = @IS_RELEASE_TREE@
|
||||||
|
JAVA_MAJOR_VERSION = @JAVA_MAJOR_VERSION@
|
||||||
|
JAVAC = @JAVAC@
|
||||||
|
LDD = @LDD@
|
||||||
|
LDFLAGS = @LDFLAGS@
|
||||||
|
libdir = @libdir@
|
||||||
|
# override in your `make` command to make the install relocatable
|
||||||
|
libdir_relative_to_bindir = $(libdir)
|
||||||
|
LIBRARY_PATH = @LIBRARY_PATH@
|
||||||
|
LIBS = @LIBS@
|
||||||
|
mandir = @mandir@
|
||||||
|
MENHIR = @MENHIR@
|
||||||
|
MKDIR_P_CMD = case "@MKDIR_P@" in \
|
||||||
|
./*) printf "$(ROOT_DIR)/@MKDIR_P@\n";; \
|
||||||
|
*) printf "@MKDIR_P@\n";; \
|
||||||
|
esac
|
||||||
|
MKDIR_P = $(shell $(MKDIR_P_CMD))
|
||||||
|
MVN = @MVN@
|
||||||
|
NCPU = @NCPU@
|
||||||
|
NDKBUILD = @NDKBUILD@
|
||||||
|
NINJA = @NINJA@
|
||||||
|
OCAMLBUILD = @OCAMLBUILD@
|
||||||
|
OCAMLC = @OCAMLC@
|
||||||
|
OCAMLFIND = @OCAMLFIND@
|
||||||
|
OCAMLFORMAT_EXE = @OCAMLFORMAT@
|
||||||
|
OCAMLLEX = @OCAMLLEX@
|
||||||
|
OCAMLOPT = @OCAMLOPT@
|
||||||
|
OPAM = @OPAM@
|
||||||
|
OPAMROOT = @OPAMROOT@
|
||||||
|
OPAMSWITCH = @OPAMSWITCH@
|
||||||
|
OTOOL = @OTOOL@
|
||||||
|
PATCHELF = @PATCHELF@
|
||||||
|
PATH = @PATH@
|
||||||
|
prefix = @prefix@
|
||||||
|
REBAR3 = @REBAR3@
|
||||||
|
SDKROOT = @SDKROOT@
|
||||||
|
SHASUM = @SHASUM@
|
||||||
|
USER_JAVA_HOME = @USER_JAVA_HOME@
|
||||||
|
UTOP = @UTOP@
|
||||||
|
WINDOWS_BUILD = @WINDOWS_BUILD@
|
||||||
|
XCODE_BASE = @XCODE_BASE@
|
||||||
|
XCODE_SELECT = @XCODE_SELECT@
|
||||||
|
XCPRETTY = @XCPRETTY@
|
||||||
|
XCRUN = @XCRUN@
|
||||||
|
|
||||||
|
ifneq (,$(findstring s,$(MAKEFLAGS)))
|
||||||
|
# quiet mode
|
||||||
|
LN_S = @LN_S@
|
||||||
|
else
|
||||||
|
LN_S = @LN_S@ -v
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Export parts of the config relevant to running other programs
|
||||||
|
export PATH := $(PATH)
|
||||||
|
export CPATH := $(CPATH)
|
||||||
|
export LIBRARY_PATH := $(LIBRARY_PATH)
|
||||||
|
export CAML_LD_LIBRARY_PATH := $(CAML_LD_LIBRARY_PATH)
|
||||||
|
export OPAMROOT := $(OPAMROOT)
|
||||||
|
export SDKROOT := $(SDKROOT)
|
@ -0,0 +1,211 @@
|
|||||||
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
#
|
||||||
|
# This source code is licensed under the MIT license found in the
|
||||||
|
# LICENSE file in the root directory of this source tree.
|
||||||
|
|
||||||
|
ORIG_SHELL = $(shell echo "$$SHELL")
|
||||||
|
SHELL = bash -e -o pipefail -u
|
||||||
|
|
||||||
|
ORIG_SHELL_PATH = $(shell printf "%s" "$$PATH")
|
||||||
|
|
||||||
|
# Make infer crash a bit more often to detect issues in the way we call infer within this repo, eg,
|
||||||
|
# using deprecated options.
|
||||||
|
export INFER_STRICT_MODE=1
|
||||||
|
|
||||||
|
include $(ROOT_DIR)/Makefile.autoconf
|
||||||
|
|
||||||
|
# possible values:
|
||||||
|
# - dev: flambda optimizations disabled, build warnings are errors
|
||||||
|
# - dev-noerror: flambda optimizations disabled, build warnings do not fail the build
|
||||||
|
# - opt: flambda optimizations enabled, build warnings do not fail the build
|
||||||
|
BUILD_MODE = dev
|
||||||
|
DUNE_BUILD = dune build --profile=$(BUILD_MODE)
|
||||||
|
|
||||||
|
PLATFORM = $(shell uname)
|
||||||
|
|
||||||
|
COPY = cp -f
|
||||||
|
COPY_DIR = cp -Rf
|
||||||
|
REMOVE = rm -f
|
||||||
|
REMOVE_DIR = rm -rf
|
||||||
|
|
||||||
|
ABSOLUTE_ROOT_DIR = $(shell cd $(ROOT_DIR) && pwd)
|
||||||
|
|
||||||
|
DEPENDENCIES_DIR = $(ABSOLUTE_ROOT_DIR)/dependencies
|
||||||
|
DOCKER_DIR = $(ABSOLUTE_ROOT_DIR)/docker
|
||||||
|
EXAMPLES_DIR = $(ABSOLUTE_ROOT_DIR)/examples
|
||||||
|
INFER_DIR = $(ABSOLUTE_ROOT_DIR)/infer
|
||||||
|
FCP_DIR = $(ABSOLUTE_ROOT_DIR)/facebook-clang-plugins
|
||||||
|
M4_DIR = $(ABSOLUTE_ROOT_DIR)/m4
|
||||||
|
SCRIPT_DIR = $(ABSOLUTE_ROOT_DIR)/scripts
|
||||||
|
WEBSITE_DIR = $(ABSOLUTE_ROOT_DIR)/website
|
||||||
|
|
||||||
|
FCP_CLANG_OCAML_DIR = $(FCP_DIR)/clang-ocaml
|
||||||
|
|
||||||
|
ANNOTATIONS_DIR = $(INFER_DIR)/annotations
|
||||||
|
BIN_DIR = $(INFER_DIR)/bin
|
||||||
|
ETC_DIR = $(INFER_DIR)/etc
|
||||||
|
LIB_DIR = $(INFER_DIR)/lib
|
||||||
|
MAN_DIR = $(INFER_DIR)/man
|
||||||
|
MODELS_DIR = $(INFER_DIR)/models
|
||||||
|
JAVA_BUILTINS_DIR = $(MODELS_DIR)/java/builtins
|
||||||
|
JAVA_MODELS_DIR = $(MODELS_DIR)/java/src
|
||||||
|
SRC_DIR = $(INFER_DIR)/src
|
||||||
|
|
||||||
|
BUILD_DIR = $(INFER_DIR)/_build
|
||||||
|
|
||||||
|
JAVA_LIB_DIR = $(LIB_DIR)/java
|
||||||
|
|
||||||
|
INFER_BIN = $(BIN_DIR)/infer
|
||||||
|
INFER_COMMANDS = \
|
||||||
|
infer-analyze \
|
||||||
|
infer-capture \
|
||||||
|
infer-compile \
|
||||||
|
infer-debug \
|
||||||
|
infer-explore \
|
||||||
|
infer-help \
|
||||||
|
infer-report \
|
||||||
|
infer-reportdiff \
|
||||||
|
infer-run \
|
||||||
|
|
||||||
|
INFERTOP_BIN = $(BIN_DIR)/infertop.bc.exe
|
||||||
|
INFERUNIT_BIN = $(BIN_DIR)/inferunit.bc.exe
|
||||||
|
CHECKCOPYRIGHT_BIN = $(BIN_DIR)/checkCopyright
|
||||||
|
|
||||||
|
INFER_CREATE_TRACEVIEW_LINKS = InferCreateTraceViewLinks
|
||||||
|
INFER_CREATE_TRACEVIEW_LINKS_BIN = $(BIN_DIR)/$(INFER_CREATE_TRACEVIEW_LINKS)
|
||||||
|
|
||||||
|
INFER_COMMAND_MANUALS = $(INFER_COMMANDS:%=$(MAN_DIR)/man1/%.1)
|
||||||
|
INFER_COMMAND_TEXT_MANUALS = $(INFER_COMMANDS:%=$(MAN_DIR)/man1/%.txt)
|
||||||
|
INFER_MANUAL = $(MAN_DIR)/man1/infer.1
|
||||||
|
INFER_GROFF_MANUALS = $(INFER_COMMAND_MANUALS) $(INFER_MANUAL)
|
||||||
|
INFER_GROFF_MANUALS_GZIPPED = $(INFER_GROFF_MANUALS:=.gz)
|
||||||
|
INFER_TEXT_MANUAL = $(MAN_DIR)/man1/infer.txt
|
||||||
|
INFER_FULL_TEXT_MANUAL = $(MAN_DIR)/man1/infer-full.txt
|
||||||
|
INFER_TEXT_MANUALS = $(INFER_COMMAND_TEXT_MANUALS) $(INFER_TEXT_MANUAL) $(INFER_FULL_TEXT_MANUAL)
|
||||||
|
INFER_MANUALS = $(INFER_GROFF_MANUALS) $(INFER_TEXT_MANUALS)
|
||||||
|
|
||||||
|
ifeq ($(BUILD_JAVA_ANALYZERS),yes)
|
||||||
|
JAVA_HOME=$(USER_JAVA_HOME)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# marker to keep track of when models have been rebuilt
|
||||||
|
MODELS_RESULTS_FILE = $(LIB_DIR)/models.sql
|
||||||
|
|
||||||
|
ANDROID_JAR = $(LIB_DIR)/java/android/android-23.jar
|
||||||
|
GUAVA_JAR = $(DEPENDENCIES_DIR)/java/guava/guava-23.0.jar
|
||||||
|
INFER_ANNOTATIONS_JAR = $(ANNOTATIONS_DIR)/annotations.jar
|
||||||
|
JACKSON_JAR = $(DEPENDENCIES_DIR)/java/jackson/jackson-2.2.3.jar
|
||||||
|
JSR_305_JAR = $(DEPENDENCIES_DIR)/java/jsr-305/jsr305.jar
|
||||||
|
|
||||||
|
JAVA_MODELS_JAR = $(LIB_DIR)/java/models.jar
|
||||||
|
|
||||||
|
JAVA_DEPS_NO_MODELS = \
|
||||||
|
$(ANDROID_JAR) $(GUAVA_JAR) $(JACKSON_JAR) $(JSR_305_JAR) $(INFER_ANNOTATIONS_JAR) \
|
||||||
|
$(INFER_BIN)
|
||||||
|
|
||||||
|
JAVA_DEPS = $(JAVA_DEPS_NO_MODELS) $(JAVA_MODELS_JAR) $(MODELS_RESULTS_FILE)
|
||||||
|
|
||||||
|
CLANG_DEPS_NO_MODELS = $(INFER_BIN)
|
||||||
|
|
||||||
|
CLANG_DEPS = $(CLANG_DEPS_NO_MODELS) $(MODELS_RESULTS_FILE)
|
||||||
|
|
||||||
|
XCODE_ISYSROOT_SUFFIX = Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk
|
||||||
|
ifeq ($(wildcard $(XCODE_BASE)/$(XCODE_ISYSROOT_SUFFIX)),)
|
||||||
|
XCODE_ISYSROOT_SUFFIX = SDKs/MacOSX.sdk
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(HAS_OBJC),yes)
|
||||||
|
XCODE_ISYSROOT = $(XCODE_BASE)/$(XCODE_ISYSROOT_SUFFIX)
|
||||||
|
endif
|
||||||
|
|
||||||
|
define copy_or_same_file
|
||||||
|
$(COPY) "$(1)" "$(2)" || diff -q "$(1)" "$(2)"
|
||||||
|
endef
|
||||||
|
|
||||||
|
INTERACTIVE = $(shell [ -t 0 ] && echo 1)
|
||||||
|
SILENT = $(findstring s,$(filter-out -%,$(firstword $(MAKEFLAGS))))
|
||||||
|
|
||||||
|
ifeq (1,$(INTERACTIVE))
|
||||||
|
TERM_ERROR = $(shell printf '\e[31;1m')
|
||||||
|
TERM_INFO = $(shell printf '\e[;1m')
|
||||||
|
TERM_SUCCESS = $(shell printf '\e[;2m')
|
||||||
|
TERM_RESET = $(shell printf '\e[0m')
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(VERBOSE),1)
|
||||||
|
# quiet
|
||||||
|
QUIET = @
|
||||||
|
endif
|
||||||
|
|
||||||
|
MAKE := $(MAKE) INTERACTIVE=$(INTERACTIVE)
|
||||||
|
|
||||||
|
# check if pid_max can be found else default to whatever
|
||||||
|
KERNEL_PID_MAX_FILE = /proc/sys/kernel/pid_max
|
||||||
|
MAX_PID_SIZE = $(shell \
|
||||||
|
[ -r $(KERNEL_PID_MAX_FILE) ] \
|
||||||
|
&& echo $$(( $$(wc -m < $(KERNEL_PID_MAX_FILE)) - 1 )) \
|
||||||
|
|| echo 5)
|
||||||
|
|
||||||
|
# Arguments:
|
||||||
|
# $(1) is a string describing the command
|
||||||
|
# $(2) is the command to run
|
||||||
|
#
|
||||||
|
ifeq ($(VERBOSE),1)
|
||||||
|
define silent_on_success
|
||||||
|
$(2)
|
||||||
|
endef
|
||||||
|
else
|
||||||
|
# Run and time the command and redirect its stdout and stderr to files. Display info about the
|
||||||
|
# command only in case of error. Try to be as helpful as possible in the error case.
|
||||||
|
#
|
||||||
|
# The PID of the process is used in the names of the output files, and as a prefix for each error
|
||||||
|
# message so that it's possible to piece error messages together even when they are interleaved with
|
||||||
|
# other messages from concurrent `make` processes.
|
||||||
|
#
|
||||||
|
# Detect if we are already wrapped inside a silent_on_success call and try not to clutter the output
|
||||||
|
# too much in that case.
|
||||||
|
define silent_on_success
|
||||||
|
if [ -n "$${INSIDE_SILENT_ON_SUCCESS-}" ]; then \
|
||||||
|
echo '*** inner $(1)'; \
|
||||||
|
echo '*** inner command: $(2)'; \
|
||||||
|
echo '*** inner CWD: $(CURDIR)'; \
|
||||||
|
($(2)); \
|
||||||
|
exit $$?; \
|
||||||
|
fi; \
|
||||||
|
export INSIDE_SILENT_ON_SUCCESS=1; \
|
||||||
|
HASH="$$$$"; \
|
||||||
|
UNIX_START_DATE=$$(date +"%s"); \
|
||||||
|
HUMAN_START_DATE=$$(date +"%H:%M:%S"); \
|
||||||
|
if [ -z $(SILENT) ]; then \
|
||||||
|
printf '[%s][%$(MAX_PID_SIZE)s] $(TERM_INFO)%s...$(TERM_RESET)\n' \
|
||||||
|
"$$HUMAN_START_DATE" "$$HASH" "$(1)"; \
|
||||||
|
fi; \
|
||||||
|
$(MKDIR_P) $(ABSOLUTE_ROOT_DIR)/_build_logs; \
|
||||||
|
ERRCODE=0; \
|
||||||
|
($(2)) 1>$(ABSOLUTE_ROOT_DIR)/_build_logs/cmd-$$HASH.out \
|
||||||
|
2>$(ABSOLUTE_ROOT_DIR)/_build_logs/cmd-$$HASH.err \
|
||||||
|
|| ERRCODE=$$?; \
|
||||||
|
if [ $$ERRCODE != 0 ]; then \
|
||||||
|
echo "$(TERM_ERROR)[*ERROR**][$$HASH] *** ERROR '$(1)'$(TERM_RESET)" >&2; \
|
||||||
|
echo "$(TERM_ERROR)[*ERROR**][$$HASH] *** command: '$(2)'$(TERM_RESET)" >&2; \
|
||||||
|
echo "$(TERM_ERROR)[*ERROR**][$$HASH] *** CWD: '$(CURDIR)'$(TERM_RESET)" >&2; \
|
||||||
|
echo "$(TERM_ERROR)[*ERROR**][$$HASH] *** stdout:$(TERM_RESET)" >&2; \
|
||||||
|
sed -e "s/^\(.*\)$$/$(TERM_ERROR)[*ERROR**][$$HASH]$(TERM_RESET) \1/" \
|
||||||
|
$(ABSOLUTE_ROOT_DIR)/_build_logs/cmd-$$HASH.out; >&2; \
|
||||||
|
echo "$(TERM_ERROR)[*ERROR**][$$HASH] *** stderr:$(TERM_RESET)" >&2; \
|
||||||
|
sed -e "s/^\(.*\)$$/$(TERM_ERROR)[*ERROR**][$$HASH]$(TERM_RESET) \1/" \
|
||||||
|
$(ABSOLUTE_ROOT_DIR)/_build_logs/cmd-$$HASH.err; >&2; \
|
||||||
|
exit $$ERRCODE; \
|
||||||
|
elif [ -z $(SILENT) ]; then \
|
||||||
|
UNIX_END_DATE=$$(date +"%s"); \
|
||||||
|
printf '[%7ss][%$(MAX_PID_SIZE)s] $(TERM_SUCCESS)SUCCESS %s$(TERM_RESET)\n' \
|
||||||
|
"$$(($$UNIX_END_DATE - $$UNIX_START_DATE))" "$$HASH" "$(1)"; \
|
||||||
|
fi
|
||||||
|
endef
|
||||||
|
endif
|
||||||
|
|
||||||
|
# print any variable for Makefile debugging
|
||||||
|
print-%:
|
||||||
|
$(QUIET)echo '$*=$($*)'
|
||||||
|
|
||||||
|
TESTLOCK = $(INFER_DIR)/tests/testlock.py
|
@ -0,0 +1 @@
|
|||||||
|
Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for how to set up your development environment and run tests.
|
@ -0,0 +1,24 @@
|
|||||||
|
<img src="website/static/img/logo.png" alt="logo" width="15%" />
|
||||||
|
|
||||||
|
# Infer [![Build Status](https://travis-ci.org/facebook/infer.svg?branch=master)](https://travis-ci.org/facebook/infer)
|
||||||
|
|
||||||
|
[Infer](http://fbinfer.com/) is a static analysis tool for Java,
|
||||||
|
C++, Objective-C, and C. Infer is written in [OCaml](https://ocaml.org/).
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Read our [Getting
|
||||||
|
Started](http://fbinfer.com/docs/getting-started) page for
|
||||||
|
details on how to install packaged versions of Infer. To build Infer
|
||||||
|
from source, see [INSTALL.md](./INSTALL.md).
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
See [CONTRIBUTING.md](./CONTRIBUTING.md).
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Infer is MIT-licensed.
|
||||||
|
|
||||||
|
Note: Enabling Java support may require you to download and install
|
||||||
|
components licensed under the GPL.
|
@ -0,0 +1,59 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
#
|
||||||
|
# This source code is licensed under the MIT license found in the
|
||||||
|
# LICENSE file in the root directory of this source tree.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
# make sure we run from the root of the repo
|
||||||
|
pushd "$SCRIPT_DIR" > /dev/null
|
||||||
|
|
||||||
|
# We need to record the date that the documentation was last modified to put in our man
|
||||||
|
# pages. Unfortunately that information is only available reliably from `git`, which we don't have
|
||||||
|
# access to from other distributions of the infer source code. Such source distributions should
|
||||||
|
# distribute the "configure" script too. The idea is to bake this date inside "configure" so that
|
||||||
|
# it's available at build time. We do that by generating an m4 macro that hardcodes the date we
|
||||||
|
# compute in this script for "configure" to find.
|
||||||
|
MAN_LAST_MODIFIED_M4=m4/__GENERATED__ac_check_infer_man_last_modified.m4
|
||||||
|
printf 'generating %s' "$MAN_LAST_MODIFIED_M4... "
|
||||||
|
if test -d '.git' ; then
|
||||||
|
# date at which the man pages were last modified, to record in the manpages themselves
|
||||||
|
MAN_FILES=(
|
||||||
|
infer/src/base/CommandLineOption.ml
|
||||||
|
infer/src/base/Config.ml
|
||||||
|
)
|
||||||
|
MAN_DATE=$(git log -n 1 --pretty=format:%cd --date=short -- "${MAN_FILES[@]}")
|
||||||
|
INFER_MAN_LAST_MODIFIED=${INFER_MAN_LAST_MODIFIED:-$MAN_DATE}
|
||||||
|
else
|
||||||
|
echo 'no git repository detected; setting last modified date to today'
|
||||||
|
# best effort: get today's date
|
||||||
|
INFER_MAN_LAST_MODIFIED=${INFER_MAN_LAST_MODIFIED:-$(date +%Y-%m-%d)}
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf "AC_DEFUN([AC_CHECK_INFER_MAN_LAST_MODIFIED],\n" > "$MAN_LAST_MODIFIED_M4"
|
||||||
|
printf "[INFER_MAN_LAST_MODIFIED=%s\n" "$INFER_MAN_LAST_MODIFIED" >> "$MAN_LAST_MODIFIED_M4"
|
||||||
|
printf " AC_SUBST([INFER_MAN_LAST_MODIFIED])\n" >> "$MAN_LAST_MODIFIED_M4"
|
||||||
|
printf "])\n" >> "$MAN_LAST_MODIFIED_M4"
|
||||||
|
printf 'done\n'
|
||||||
|
|
||||||
|
# older versions of `autoreconf` only support including macros via acinclude.m4
|
||||||
|
ACINCLUDE="acinclude.m4"
|
||||||
|
printf "generating $ACINCLUDE..."
|
||||||
|
cat m4/*.m4 > "$ACINCLUDE"
|
||||||
|
printf " done\n"
|
||||||
|
|
||||||
|
printf "generating ./configure script..."
|
||||||
|
autoreconf -fi
|
||||||
|
printf " done\n"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "you may now run the following commands to build Infer:"
|
||||||
|
echo ""
|
||||||
|
echo " ./configure"
|
||||||
|
echo " make"
|
||||||
|
echo ""
|
||||||
|
echo 'run `./configure --help` for more options'
|
@ -0,0 +1,232 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Convenience script to build Infer when using opam
|
||||||
|
|
||||||
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
#
|
||||||
|
# This source code is licensed under the MIT license found in the
|
||||||
|
# LICENSE file in the root directory of this source tree.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
set -o pipefail
|
||||||
|
set -u
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
INFER_ROOT="$SCRIPT_DIR"
|
||||||
|
DEPENDENCIES_DIR="$INFER_ROOT/facebook/dependencies"
|
||||||
|
PLATFORM="$(uname)"
|
||||||
|
SANDCASTLE=${SANDCASTLE:-}
|
||||||
|
NCPU="$(getconf _NPROCESSORS_ONLN 2>/dev/null || echo 1)"
|
||||||
|
INFER_OPAM_DEFAULT_SWITCH="4.12.0+flambda"
|
||||||
|
INFER_OPAM_DEFAULT_SWITCH_OPTIONS="--package=ocaml-variants.4.12.0+options,ocaml-option-flambda"
|
||||||
|
INFER_OPAM_SWITCH=${INFER_OPAM_SWITCH:-$INFER_OPAM_DEFAULT_SWITCH}
|
||||||
|
INFER_OPAM_SWITCH_OPTIONS=${INFER_OPAM_SWITCH_OPTIONS:-$INFER_OPAM_DEFAULT_SWITCH_OPTIONS}
|
||||||
|
PLUGIN_DIR="$INFER_ROOT/facebook-clang-plugins"
|
||||||
|
PLUGIN_SETUP_SCRIPT=${PLUGIN_SETUP_SCRIPT:-setup.sh}
|
||||||
|
PLUGIN_SETUP="${PLUGIN_DIR}/clang/${PLUGIN_SETUP_SCRIPT}"
|
||||||
|
|
||||||
|
function usage() {
|
||||||
|
echo "Usage: $0 [-y] [targets]"
|
||||||
|
echo
|
||||||
|
echo " targets:"
|
||||||
|
echo " all build everything (default)"
|
||||||
|
echo " clang build C and Objective-C analyzer"
|
||||||
|
echo " erlang build Erlang analyzer"
|
||||||
|
echo " java build Java analyzer"
|
||||||
|
echo
|
||||||
|
echo " options:"
|
||||||
|
echo " -h,--help show this message"
|
||||||
|
echo " --no-opam-lock do not use the opam/infer.opam.locked file and let opam resolve dependencies"
|
||||||
|
echo " --only-setup-opam initialize opam, install the opam dependencies of infer, and exit"
|
||||||
|
echo " --user-opam-switch use the current opam switch to install infer (default: $INFER_OPAM_DEFAULT_SWITCH)"
|
||||||
|
echo " -y,--yes automatically agree to everything"
|
||||||
|
echo
|
||||||
|
echo " examples:"
|
||||||
|
echo " $0 # build Java, Erlang and C/Objective-C analyzers"
|
||||||
|
echo " $0 java erlang clang # equivalent way of doing the above"
|
||||||
|
echo " $0 java # build only the Java analyzer"
|
||||||
|
}
|
||||||
|
|
||||||
|
# arguments
|
||||||
|
BUILD_CLANG=${BUILD_CLANG:-no}
|
||||||
|
BUILD_ERLANG=${BUILD_ERLANG:-no}
|
||||||
|
BUILD_JAVA=${BUILD_JAVA:-no}
|
||||||
|
INFER_CONFIGURE_OPTS=${INFER_CONFIGURE_OPTS:-""}
|
||||||
|
INTERACTIVE=${INTERACTIVE:-yes}
|
||||||
|
JOBS=${JOBS:-$NCPU}
|
||||||
|
ONLY_SETUP_OPAM=${ONLY_SETUP_OPAM:-no}
|
||||||
|
USE_OPAM_LOCK=${USE_OPAM_LOCK:-yes}
|
||||||
|
USER_OPAM_SWITCH=no
|
||||||
|
|
||||||
|
ORIG_ARGS="$*"
|
||||||
|
|
||||||
|
function build_all() {
|
||||||
|
BUILD_CLANG=yes
|
||||||
|
BUILD_ERLANG=yes
|
||||||
|
BUILD_JAVA=yes
|
||||||
|
}
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
opt_key="$1"
|
||||||
|
case $opt_key in
|
||||||
|
all)
|
||||||
|
build_all
|
||||||
|
shift
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
clang)
|
||||||
|
BUILD_CLANG=yes
|
||||||
|
shift
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
erlang)
|
||||||
|
BUILD_ERLANG=yes
|
||||||
|
shift
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
java)
|
||||||
|
BUILD_JAVA=yes
|
||||||
|
shift
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
--no-opam-lock)
|
||||||
|
USE_OPAM_LOCK=no
|
||||||
|
shift
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
--user-opam-switch)
|
||||||
|
USER_OPAM_SWITCH=yes
|
||||||
|
shift
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
--only-setup-opam)
|
||||||
|
ONLY_SETUP_OPAM=yes
|
||||||
|
shift
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
-y|--yes)
|
||||||
|
INTERACTIVE=no
|
||||||
|
shift
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$BUILD_CLANG" == "no" ] && [ "$BUILD_ERLANG" == "no" ] && [ "$BUILD_JAVA" == "no" ]; then
|
||||||
|
build_all
|
||||||
|
fi
|
||||||
|
|
||||||
|
# enable --yes option for some commands in non-interactive mode
|
||||||
|
YES=
|
||||||
|
if [ "$INTERACTIVE" == "no" ]; then
|
||||||
|
YES=--yes
|
||||||
|
fi
|
||||||
|
# --yes by default for opam commands except if we are using the user's opam switch
|
||||||
|
if [ "$INTERACTIVE" == "no" ] || [ "$USER_OPAM_SWITCH" == "no" ]; then
|
||||||
|
export OPAMYES=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
setup_opam () {
|
||||||
|
opam var root 1>/dev/null 2>/dev/null || opam init --reinit --bare --no-setup &&
|
||||||
|
opam_retry opam_switch_create_if_needed "$INFER_OPAM_SWITCH" "$INFER_OPAM_SWITCH_OPTIONS" &&
|
||||||
|
opam switch set "$INFER_OPAM_SWITCH"
|
||||||
|
}
|
||||||
|
|
||||||
|
install_opam_deps () {
|
||||||
|
local locked=
|
||||||
|
if [ "$USE_OPAM_LOCK" == yes ]; then
|
||||||
|
locked=.locked
|
||||||
|
fi
|
||||||
|
opam install --deps-only "$INFER_ROOT"/opam/infer.opam$locked &&
|
||||||
|
if [ -n "$SANDCASTLE" ]; then
|
||||||
|
opam pin list | grep yojson || opam pin add yojson "${DEPENDENCIES_DIR}/yojson-1.7.0fix"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "initializing opam... " >&2
|
||||||
|
. "$INFER_ROOT"/scripts/opam_utils.sh
|
||||||
|
if [ "$USER_OPAM_SWITCH" == "no" ]; then
|
||||||
|
setup_opam
|
||||||
|
fi
|
||||||
|
eval $(SHELL=bash opam env)
|
||||||
|
echo >&2
|
||||||
|
echo "installing infer dependencies; this can take up to 30 minutes... " >&2
|
||||||
|
opam_retry install_opam_deps
|
||||||
|
|
||||||
|
if [ "$ONLY_SETUP_OPAM" == "yes" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "preparing build... " >&2
|
||||||
|
./autogen.sh > /dev/null
|
||||||
|
|
||||||
|
if [ "$BUILD_CLANG" == "no" ]; then
|
||||||
|
INFER_CONFIGURE_OPTS+=" --disable-c-analyzers"
|
||||||
|
fi
|
||||||
|
if [ "$BUILD_ERLANG" == "no" ]; then
|
||||||
|
INFER_CONFIGURE_OPTS+=" --disable-erlang-analyzers"
|
||||||
|
fi
|
||||||
|
if [ "$BUILD_JAVA" == "no" ]; then
|
||||||
|
INFER_CONFIGURE_OPTS+=" --disable-java-analyzers"
|
||||||
|
fi
|
||||||
|
|
||||||
|
./configure $INFER_CONFIGURE_OPTS
|
||||||
|
|
||||||
|
if [ "$BUILD_CLANG" == "yes" ]; then
|
||||||
|
if ! "$PLUGIN_SETUP" --only-check-install; then
|
||||||
|
echo ""
|
||||||
|
echo " Warning: you are not using a release of Infer. The C and"
|
||||||
|
echo " Objective-C analyses require a custom clang to be compiled"
|
||||||
|
echo " now. This step takes ~30-60 minutes, possibly more."
|
||||||
|
echo ""
|
||||||
|
echo " To speed this along, you are encouraged to use a release of"
|
||||||
|
echo " Infer instead:"
|
||||||
|
echo ""
|
||||||
|
echo " http://fbinfer.com/docs/getting-started"
|
||||||
|
echo ""
|
||||||
|
echo " If you are only interested in analyzing Java programs, simply"
|
||||||
|
echo " run this script with only the \"java\" argument:"
|
||||||
|
echo ""
|
||||||
|
echo " $0 java"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
confirm="n"
|
||||||
|
printf "Are you sure you want to compile clang? (y/N) "
|
||||||
|
if [ "$INTERACTIVE" == "no" ]; then
|
||||||
|
confirm="y"
|
||||||
|
echo "$confirm"
|
||||||
|
else
|
||||||
|
read confirm
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "x$confirm" != "xy" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# only run this script if we are definitely building clang
|
||||||
|
facebook-clang-plugins/clang/src/prepare_clang_src.sh
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
make -j "$JOBS" opt || (
|
||||||
|
echo >&2
|
||||||
|
echo ' compilation failure; you can try running' >&2
|
||||||
|
echo >&2
|
||||||
|
echo ' make clean' >&2
|
||||||
|
echo " '$0' $ORIG_ARGS" >&2
|
||||||
|
echo >&2
|
||||||
|
exit 1)
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "*** Success! Infer is now built in '$SCRIPT_DIR/infer/bin/'."
|
||||||
|
echo '*** Install infer on your system with `make install`.'
|
||||||
|
echo
|
||||||
|
echo '*** If you plan to hack on infer, check out CONTRIBUTING.md to setup your dev environment.'
|
@ -0,0 +1,427 @@
|
|||||||
|
dnl Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
dnl
|
||||||
|
dnl This source code is licensed under the MIT license found in the
|
||||||
|
dnl LICENSE file in the root directory of this source tree.
|
||||||
|
|
||||||
|
dnl autoconf script for Infer
|
||||||
|
dnl run ./autogen.sh to generate a configure script
|
||||||
|
|
||||||
|
AC_PREREQ([2.63])
|
||||||
|
|
||||||
|
# WARNING: the version number has to be kept in sync with:
|
||||||
|
# - the values below
|
||||||
|
# - opam
|
||||||
|
AC_INIT([Infer],
|
||||||
|
[1.1.0],
|
||||||
|
[https://github.com/facebook/infer/issues/])
|
||||||
|
|
||||||
|
AC_CONFIG_SRCDIR([infer/src/istd/IStd.ml])
|
||||||
|
|
||||||
|
# WARNING: keep in sync with above
|
||||||
|
INFER_MAJOR=1
|
||||||
|
INFER_MINOR=1
|
||||||
|
INFER_PATCH=0
|
||||||
|
|
||||||
|
AC_SUBST([INFER_MAJOR])
|
||||||
|
AC_SUBST([INFER_MINOR])
|
||||||
|
AC_SUBST([INFER_PATCH])
|
||||||
|
|
||||||
|
# are we in a release source tree
|
||||||
|
AC_CHECK_FILE([.release], [is_release_tree=yes], [is_release_tree=no])
|
||||||
|
IS_RELEASE_TREE=$is_release_tree
|
||||||
|
AC_SUBST([IS_RELEASE_TREE])
|
||||||
|
|
||||||
|
# are we in an internal source tree
|
||||||
|
AC_CHECK_FILE([.facebook], [is_facebook_tree=yes], [is_facebook_tree=no])
|
||||||
|
IS_FACEBOOK_TREE=$is_facebook_tree
|
||||||
|
AC_SUBST([IS_FACEBOOK_TREE])
|
||||||
|
|
||||||
|
AC_ARG_VAR([PATH], [the shell's $PATH list of directories to search for executables])
|
||||||
|
|
||||||
|
# to compile the facebook-clang-plugins
|
||||||
|
AC_ARG_VAR([CLANG_PREFIX], [directory where clang is installed (defaults=$PWD/facebook-clang-plugins/clang/install)])
|
||||||
|
AS_IF([test "x$CLANG_PREFIX" = "x"], [
|
||||||
|
CLANG_PREFIX="$(pwd)/facebook-clang-plugins/clang/install"
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_ARG_VAR([CLANG_INCLUDES], [clang headers directories (defaults=$CLANG_PREFIX/include)])
|
||||||
|
AS_IF([test "x$CLANG_INCLUDES" = "x"], [
|
||||||
|
CLANG_INCLUDES="$CLANG_PREFIX/include"
|
||||||
|
])
|
||||||
|
|
||||||
|
BUILD_PLATFORM=unknown
|
||||||
|
WINDOWS_BUILD=no
|
||||||
|
AC_MSG_CHECKING([for build platform])
|
||||||
|
# see https://stackoverflow.com/questions/714100/os-detecting-makefile
|
||||||
|
# but we do this in the configure for homogeneity
|
||||||
|
case "${OS}" in
|
||||||
|
Windows_NT*)
|
||||||
|
BUILD_PLATFORM=Windows
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
uname_str=`uname -s`
|
||||||
|
case "${uname_str}" in
|
||||||
|
Linux*)
|
||||||
|
BUILD_PLATFORM=Linux
|
||||||
|
;;
|
||||||
|
Darwin*)
|
||||||
|
BUILD_PLATFORM=Darwin
|
||||||
|
;;
|
||||||
|
cygwin*|mingw*)
|
||||||
|
BUILD_PLATFORM=Windows
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
AC_MSG_ERROR(["OS $uname_str is not supported"])
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
esac
|
||||||
|
AC_MSG_RESULT([$BUILD_PLATFORM])
|
||||||
|
AC_SUBST([BUILD_PLATFORM])
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([for Windows build])
|
||||||
|
AS_IF([test x"$BUILD_PLATFORM" = x"Windows"], [WINDOWS_BUILD=yes])
|
||||||
|
AC_MSG_RESULT([$WINDOWS_BUILD])
|
||||||
|
AC_SUBST([WINDOWS_BUILD])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(c-analyzers,
|
||||||
|
AS_HELP_STRING([--disable-c-analyzers],
|
||||||
|
[do not build the C/C++/ObjC analyzers (default is to build them)]),
|
||||||
|
,
|
||||||
|
enable_c_analyzers=yes)
|
||||||
|
BUILD_C_ANALYZERS=$enable_c_analyzers
|
||||||
|
AC_SUBST([BUILD_C_ANALYZERS])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(erlang-analyzers,
|
||||||
|
AS_HELP_STRING([--disable-erlang-analyzers],
|
||||||
|
[do not build the Erlang analyzers (default is to build them)]),
|
||||||
|
,
|
||||||
|
enable_erlang_analyzers=yes)
|
||||||
|
BUILD_ERLANG_ANALYZERS=$enable_erlang_analyzers
|
||||||
|
AC_SUBST([BUILD_ERLANG_ANALYZERS])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(java-analyzers,
|
||||||
|
AS_HELP_STRING([--disable-java-analyzers],
|
||||||
|
[do not build the Java analyzers (default is to build them)]),
|
||||||
|
,
|
||||||
|
enable_java_analyzers=yes)
|
||||||
|
BUILD_JAVA_ANALYZERS=$enable_java_analyzers
|
||||||
|
AC_SUBST([BUILD_JAVA_ANALYZERS])
|
||||||
|
|
||||||
|
AC_ARG_WITH(fcp-clang,
|
||||||
|
AS_HELP_STRING([--with-fcp-clang],
|
||||||
|
[use $CLANG_PREFIX/bin/clang to override the default compiler (default is not to override)]),
|
||||||
|
,
|
||||||
|
with_fcp_clang=no)
|
||||||
|
|
||||||
|
AS_IF([test "x$enable_c_analyzers" = "xyes"], [
|
||||||
|
AC_MSG_CHECKING([whether to use the compilers in $CLANG_PREFIX/bin])
|
||||||
|
case "$with_fcp_clang" in
|
||||||
|
no)
|
||||||
|
AC_MSG_RESULT([no])
|
||||||
|
;;
|
||||||
|
yes)
|
||||||
|
CC=$CLANG_PREFIX/bin/clang
|
||||||
|
CXX=$CLANG_PREFIX/bin/clang++
|
||||||
|
OBJC=$CLANG_PREFIX/bin/clang
|
||||||
|
AC_MSG_RESULT([yes])
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
AC_MSG_ERROR([invalid value for --without-fcp-clang; use "yes" or "no"])
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
AC_CHECK_TOOL([SHASUM], [shasum], [no])
|
||||||
|
AC_ASSERT_PROG([shasum], [$SHASUM])
|
||||||
|
# cmake is required to build llvm+clang
|
||||||
|
AC_CHECK_TOOL([CMAKE], [cmake], [no])
|
||||||
|
AC_ASSERT_PROG([cmake], [$CMAKE])
|
||||||
|
AC_ARG_ENABLE(ocamlopt-custom-cc,
|
||||||
|
AS_HELP_STRING([--enable-ocamlopt-custom-cc], [use CC in ocamlopt invocations]),
|
||||||
|
,
|
||||||
|
enable_ocamlopt_custom_cc=no)
|
||||||
|
ENABLE_OCAMLOPT_CUSTOM_CC=$enable_ocamlopt_custom_cc
|
||||||
|
AC_SUBST([ENABLE_OCAMLOPT_CUSTOM_CC])
|
||||||
|
])
|
||||||
|
# end if($enable_c_analyzers)
|
||||||
|
|
||||||
|
AC_CHECK_TOOL([XCODE_SELECT], [xcode-select], [no])
|
||||||
|
AS_IF([test "x$XCODE_SELECT" != "xno"], [XCODE_SELECT_OUT=`xcode-select -p`])
|
||||||
|
|
||||||
|
AC_ARG_VAR([XCODE_BASE], [Install location of xcode])
|
||||||
|
AS_IF(
|
||||||
|
[test "x$XCODE_BASE" != "x"],
|
||||||
|
[AC_CHECK_FILE($XCODE_BASE,[HAS_OBJC=yes],[HAS_OBJC=no])],
|
||||||
|
[test "x$XCODE_SELECT" != "xno"],
|
||||||
|
[XCODE_BASE=$XCODE_SELECT_OUT HAS_OBJC=yes],
|
||||||
|
[HAS_OBJC=no])
|
||||||
|
|
||||||
|
AC_CHECK_TOOL([XCRUN], [xcrun], [no])
|
||||||
|
|
||||||
|
AC_ARG_VAR([SDKROOT], [path to the OSX platform SDK used by clang])
|
||||||
|
AS_IF(
|
||||||
|
[test "x$SDKROOT" = "x" && test "x$XCRUN" != "xno"],
|
||||||
|
[SDKROOT=`xcrun --sdk macosx --show-sdk-path`]
|
||||||
|
)
|
||||||
|
|
||||||
|
AC_SUBST([XCODE_BASE])
|
||||||
|
AC_SUBST([HAS_OBJC])
|
||||||
|
AC_SUBST([SDKROOT])
|
||||||
|
|
||||||
|
|
||||||
|
# prefer clang over gcc because the plugins makes use of
|
||||||
|
# clang-specific #pragma's
|
||||||
|
AC_PROG_CC(clang gcc)
|
||||||
|
AC_PROG_AWK
|
||||||
|
AC_PROG_INSTALL
|
||||||
|
AC_PROG_LN_S
|
||||||
|
AC_PROG_MAKE_SET
|
||||||
|
AC_PROG_MKDIR_P
|
||||||
|
|
||||||
|
if test "x$enable_c_analyzers" = "xyes"; then
|
||||||
|
AC_PROG_CPP
|
||||||
|
AC_PROG_CXX(clang++ g++)
|
||||||
|
# AC_PROG_CXX doesn't set CXX to "no" in case of failure (I have no words...); from the manual:
|
||||||
|
# "If none of those checks succeed, then as a last resort set CXX to g++. "
|
||||||
|
AS_IF([$CXX --version > /dev/null], [], [AC_MSG_ERROR([no C++ compiler found])])
|
||||||
|
|
||||||
|
dnl clang wants either clang version >= 3.1 or gcc version >= 4.7.2 to
|
||||||
|
dnl compile itself
|
||||||
|
AC_MSG_CHECKING([if the C/C++ compiler is recent enough])
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
|
||||||
|
#ifdef __clang__
|
||||||
|
#if __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 1)
|
||||||
|
#error compiler is too old
|
||||||
|
#endif // version check
|
||||||
|
#elif defined __GNUC__ // __clang__
|
||||||
|
#if __GNUC__ < 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ < 7 || (__GNUC_MINOR__ == 7 && __GNUC_PATCHLEVEL__ < 2)))
|
||||||
|
#error compiler is too old
|
||||||
|
#endif // version check
|
||||||
|
#endif // __GNUC__
|
||||||
|
]])],
|
||||||
|
[AC_MSG_RESULT([yes])],
|
||||||
|
[dnl
|
||||||
|
AC_MSG_RESULT([no])
|
||||||
|
AC_MSG_ERROR([
|
||||||
|
Your C/C++ compiler seems to be too old to build clang, which is
|
||||||
|
required by the facebook-clang-plugins. Please install either
|
||||||
|
gcc version >= 4.7.2 or clang version >= 3.1.
|
||||||
|
|
||||||
|
See the output of `./configure --help` to force the use of a different
|
||||||
|
C compiler.
|
||||||
|
|
||||||
|
Alternatively, you can checkout a binary release of infer:
|
||||||
|
|
||||||
|
https://github.com/facebook/infer/releases/])
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
AC_CHECK_HEADERS([fcntl.h inttypes.h limits.h locale.h malloc.h stddef.h stdint.h stdlib.h string.h sys/mount.h sys/param.h sys/socket.h sys/statfs.h sys/time.h unistd.h wchar.h wctype.h])
|
||||||
|
fi
|
||||||
|
# end if($enable_c_analyzers)
|
||||||
|
|
||||||
|
|
||||||
|
# OCaml dependencies
|
||||||
|
AC_PROG_OCAML
|
||||||
|
AC_ASSERT_PROG([ocamlc], [$OCAMLC])
|
||||||
|
# check the version of OCaml
|
||||||
|
AC_ASSERT_OCAML_MIN_VERSION([4.06.1])
|
||||||
|
AC_ASSERT_PROG([ocamlopt], [$OCAMLOPT])
|
||||||
|
AC_CHECK_TOOL([OCAMLBUILD], [ocamlbuild], [no])
|
||||||
|
AC_ASSERT_PROG([ocamlbuild], [$OCAMLBUILD])
|
||||||
|
AC_PROG_FINDLIB
|
||||||
|
AC_PROG_OCAMLLEX
|
||||||
|
AC_ASSERT_PROG([ocamllex], [$OCAMLLEX])
|
||||||
|
AC_CHECK_TOOL([MENHIR], [menhir], [no])
|
||||||
|
AC_ASSERT_PROG([menhir], [$MENHIR])
|
||||||
|
AC_ASSERT_OCAML_PKG([atdgen])
|
||||||
|
AC_ASSERT_OCAML_PKG([biniou])
|
||||||
|
AC_ASSERT_OCAML_PKG([camlzip], [zip])
|
||||||
|
AC_ASSERT_OCAML_PKG([easy-format])
|
||||||
|
AC_ASSERT_OCAML_PKG([oUnit])
|
||||||
|
AC_CHECK_TOOL([UTOP], [utop], [no])
|
||||||
|
AC_ASSERT_OCAML_PKG([yojson])
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([which ocamlformat to use])
|
||||||
|
AS_IF([test x"$is_facebook_tree" = x"yes"],
|
||||||
|
[OCAMLFORMAT="$(pwd)"/facebook/dependencies/bin/ocamlformat],
|
||||||
|
[OCAMLFORMAT=ocamlformat])
|
||||||
|
AC_MSG_RESULT([$OCAMLFORMAT])
|
||||||
|
AC_SUBST([OCAMLFORMAT])
|
||||||
|
|
||||||
|
AC_ARG_VAR([CPATH], [Additional directories to search for C headers.])
|
||||||
|
AC_ARG_VAR([LIBRARY_PATH], [Additional directories to search for C shared objects.])
|
||||||
|
AC_ARG_VAR([CAML_LD_LIBRARY_PATH],
|
||||||
|
[Additional directories to search for dynamically-loaded libraries.])
|
||||||
|
AC_ARG_VAR([OPAMROOT], [Root of the local opam installation.])
|
||||||
|
AC_ARG_VAR([OPAMSWITCH], [Opam switch used for building infer.])
|
||||||
|
|
||||||
|
AC_CHECK_TOOL([OPAM], [opam], [no])
|
||||||
|
AS_IF([test "$OPAM" != "no"], [
|
||||||
|
AC_MSG_CHECKING([opam version])
|
||||||
|
opam_version=$(opam --version)
|
||||||
|
case $opam_version in
|
||||||
|
2.*) AC_MSG_RESULT([$opam_version]); break;;
|
||||||
|
*) AC_MSG_ERROR([opam version $opam_version is not supported, please install opam version 2 instead]); break;;
|
||||||
|
esac
|
||||||
|
AC_MSG_CHECKING([current opam root])
|
||||||
|
OPAMROOT=$("$OPAM" config var root)
|
||||||
|
AC_MSG_RESULT([$OPAMROOT])
|
||||||
|
AC_MSG_CHECKING([current opam switch])
|
||||||
|
OPAMSWITCH=$("$OPAM" switch show)
|
||||||
|
AC_MSG_RESULT([$OPAMSWITCH])
|
||||||
|
], [
|
||||||
|
OPAMROOT=no
|
||||||
|
OPAMSWITCH=no
|
||||||
|
])
|
||||||
|
AC_SUBST([OPAMROOT])
|
||||||
|
AC_SUBST([OPAMSWITCH])
|
||||||
|
|
||||||
|
if test "x$enable_erlang_analyzers" = "xyes"; then
|
||||||
|
AC_CHECK_TOOL([ESCRIPT], [escript], [no])
|
||||||
|
AC_CHECK_TOOL([REBAR3], [rebar3], [no])
|
||||||
|
fi
|
||||||
|
# end if($enable_erlang_analyzers)
|
||||||
|
|
||||||
|
if test "x$enable_java_analyzers" = "xyes"; then
|
||||||
|
AC_CHECK_TOOL([JAVA], [java], [no])
|
||||||
|
AC_CHECK_TOOL([JAVAC], [javac], [no])
|
||||||
|
AC_ASSERT_PROG([javac], [$JAVAC])
|
||||||
|
AC_ASSERT_PROG([java], [$JAVA])
|
||||||
|
AC_ASSERT_OCAML_PKG([javalib])
|
||||||
|
AC_ASSERT_OCAML_PKG([sawja])
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([for Java major version])
|
||||||
|
JAVA_MAJOR_VERSION=`"$JAVAC" -version 2>&1 | head -n 1 | cut -d ' ' -f 2`
|
||||||
|
AS_IF([test "x`echo $JAVA_MAJOR_VERSION | cut -d '.' -f 1`" = "x1"], [
|
||||||
|
# version 1.8.xx -> 8
|
||||||
|
JAVA_MAJOR_VERSION=`echo $JAVA_MAJOR_VERSION | cut -d '.' -f 2`
|
||||||
|
], [
|
||||||
|
# otherwise pick the first number as the major version
|
||||||
|
JAVA_MAJOR_VERSION=`echo $JAVA_MAJOR_VERSION | cut -d '.' -f 1`
|
||||||
|
])
|
||||||
|
AC_MSG_RESULT([$JAVA_MAJOR_VERSION])
|
||||||
|
AC_SUBST([JAVA_MAJOR_VERSION])
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([for JAVA_HOME])
|
||||||
|
cat - <<_ACEOF >conftest.java
|
||||||
|
public class conftest {
|
||||||
|
public static void main(String[[]] args) {
|
||||||
|
System.out.println(System.getProperty("java.home"));
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
rm -f conftest.class
|
||||||
|
if "$JAVAC" conftest.java; then
|
||||||
|
rm -f conftest.java
|
||||||
|
_USER_JAVA_HOME=$($JAVA -cp . conftest)
|
||||||
|
if rm -f conftest.class; then
|
||||||
|
[javac_version_10_or_more=`echo "$JAVA_MAJOR_VERSION" | grep -q -e '^1[0-9]' && echo yes`]
|
||||||
|
if test "x$javac_version_10_or_more" = "xyes"; then
|
||||||
|
USER_JAVA_HOME=$_USER_JAVA_HOME
|
||||||
|
else
|
||||||
|
USER_JAVA_HOME=$_USER_JAVA_HOME/..
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
AC_MSG_ERROR([Could not run test program with $JAVA])
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
rm -f conftest.java
|
||||||
|
AC_MSG_ERROR([Could not compile test program with $JAVAC])
|
||||||
|
fi
|
||||||
|
AC_MSG_RESULT([$USER_JAVA_HOME])
|
||||||
|
AC_SUBST([USER_JAVA_HOME])
|
||||||
|
|
||||||
|
AC_CHECK_LIB([z], [inflateEnd], [ZLIB_FOUND=yes], [ZLIB_FOUND=no])
|
||||||
|
AS_IF([test x"$ZLIB_FOUND" = xno], [AC_MSG_ERROR([zlib not found.])])
|
||||||
|
fi
|
||||||
|
# end if($enable_java_analyzers)
|
||||||
|
|
||||||
|
AC_CHECK_TOOL([ATDGEN], [atdgen], [no])
|
||||||
|
AC_ASSERT_PROG([atdgen], [$ATDGEN])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(ocaml-bin-annot,
|
||||||
|
AS_HELP_STRING([--disable-ocaml-bin-annot], [do not build ocaml .cmt files]),
|
||||||
|
,
|
||||||
|
enable_ocaml_bin_annot=yes)
|
||||||
|
ENABLE_OCAML_BINANNOT=$enable_ocaml_bin_annot
|
||||||
|
AC_SUBST([ENABLE_OCAML_BINANNOT])
|
||||||
|
|
||||||
|
|
||||||
|
# We use Buck to run the Infer tests
|
||||||
|
AS_IF([test x"$is_facebook_tree" = x"yes"],
|
||||||
|
AC_MSG_CHECKING([which .buckjavaversion to use])
|
||||||
|
cp "facebook/dependencies/dotbuckjavaversion" ".buckjavaversion"
|
||||||
|
AC_MSG_RESULT([facebook/dependencies/dotbuckjavaversion])
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([which .buck-java11 to use])
|
||||||
|
cp "facebook/dependencies/dotbuck-java11" ".buck-java11"
|
||||||
|
AC_MSG_RESULT([facebook/dependencies/dotbuck-java11]))
|
||||||
|
|
||||||
|
|
||||||
|
AC_CHECK_TOOL([GETCONF], [getconf], [no])
|
||||||
|
AC_MSG_CHECKING([the number of cpus the build host has])
|
||||||
|
if test "$GETCONF" != "no"; then
|
||||||
|
if test $("$GETCONF" _NPROCESSORS_ONLN); then
|
||||||
|
NCPU=$("$GETCONF" _NPROCESSORS_ONLN)
|
||||||
|
AC_MSG_RESULT([$NCPU])
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
NCPU=1
|
||||||
|
AC_MSG_RESULT([failed, defaulting to 1])
|
||||||
|
fi
|
||||||
|
AC_SUBST([NCPU])
|
||||||
|
|
||||||
|
# optional progs and libraries that, eg build systems to be run in integration tests
|
||||||
|
|
||||||
|
AC_CHECK_TOOL([ANT], [ant], [no])
|
||||||
|
AC_CHECK_TOOL([BUCK], [buck], [no])
|
||||||
|
AC_CHECK_TOOL([EMACS], [emacs], [no])
|
||||||
|
AC_ARG_VAR([MVN], [command to execute Maven when running tests])
|
||||||
|
AS_IF([test "x$MVN" = "x"], [
|
||||||
|
AC_CHECK_TOOL([MVN], [mvn], [no])
|
||||||
|
], [
|
||||||
|
AC_MSG_RESULT([checking for mvn... $MVN])
|
||||||
|
])
|
||||||
|
AC_CHECK_TOOL([NDKBUILD], [ndk-build], [no])
|
||||||
|
if test x"$NDKBUILD" = x"no"; then
|
||||||
|
# ndk-build not in $PATH, look into potential android NDK install paths and record the absolute path
|
||||||
|
# to ndk-build
|
||||||
|
AC_PATH_PROG([NDKBUILD], [ndk-build], [no],
|
||||||
|
[$PATH$PATH_SEPARATOR$ANDROID_NDK$PATH_SEPARATOR/opt/android_ndk/r15c])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_CHECK_TOOL([NINJA], [ninja], [no])
|
||||||
|
AC_CHECK_TOOL([XCPRETTY], [xcpretty], [no])
|
||||||
|
|
||||||
|
AC_CHECK_TOOL([SED], [sed], [no])
|
||||||
|
AS_IF([test "$SED" != "xno"], [
|
||||||
|
AC_MSG_CHECKING([if sed is GNU sed])
|
||||||
|
AS_IF(["$SED" --version 2> /dev/null | grep -q -e "GNU sed"], [
|
||||||
|
GNU_SED="$SED"
|
||||||
|
AC_MSG_RESULT([yes])
|
||||||
|
], [
|
||||||
|
AC_MSG_RESULT([no])
|
||||||
|
AC_CHECK_TOOL([GNU_SED], [gsed], [no])
|
||||||
|
])
|
||||||
|
])
|
||||||
|
AC_SUBST([GNU_SED])
|
||||||
|
|
||||||
|
AC_CHECK_TOOL([BREW], [brew], [no])
|
||||||
|
|
||||||
|
AC_CHECK_TOOL([INSTALL_NAME_TOOL], [install_name_tool], [no])
|
||||||
|
AC_SUBST([INSTALL_NAME_TOOL])
|
||||||
|
AC_CHECK_TOOL([LDD], [ldd], [no])
|
||||||
|
AC_SUBST([LDD])
|
||||||
|
AC_CHECK_TOOL([OTOOL], [otool], [no])
|
||||||
|
AC_SUBST([OTOOL])
|
||||||
|
AC_CHECK_TOOL([PATCHELF], [patchelf], [no])
|
||||||
|
AC_SUBST([PATCHELF])
|
||||||
|
|
||||||
|
AC_CHECK_INFER_MAN_LAST_MODIFIED()
|
||||||
|
|
||||||
|
AC_CONFIG_FILES([
|
||||||
|
Makefile.autoconf
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_OUTPUT
|
@ -0,0 +1,17 @@
|
|||||||
|
java_library(
|
||||||
|
name = 'java_libraries',
|
||||||
|
deps=[
|
||||||
|
'//dependencies/java/guava:guava',
|
||||||
|
'//dependencies/java/junit:hamcrest',
|
||||||
|
'//dependencies/java/jackson:jackson',
|
||||||
|
'//dependencies/java/jsr-305:jsr-305',
|
||||||
|
'//dependencies/java/junit:junit',
|
||||||
|
'//dependencies/java/opencsv:opencsv'
|
||||||
|
],
|
||||||
|
visibility = [
|
||||||
|
'PUBLIC'
|
||||||
|
]
|
||||||
|
)
|
||||||
|
project_config(
|
||||||
|
src_target = ':java_libraries',
|
||||||
|
)
|
@ -0,0 +1,7 @@
|
|||||||
|
prebuilt_jar(
|
||||||
|
name = 'android-support-v4',
|
||||||
|
binary_jar = 'android-support-v4.jar',
|
||||||
|
visibility = [
|
||||||
|
'PUBLIC',
|
||||||
|
],
|
||||||
|
)
|
Binary file not shown.
@ -0,0 +1,7 @@
|
|||||||
|
prebuilt_jar(
|
||||||
|
name = 'guava',
|
||||||
|
binary_jar = 'guava-23.0.jar',
|
||||||
|
visibility = [
|
||||||
|
'PUBLIC'
|
||||||
|
]
|
||||||
|
)
|
Binary file not shown.
@ -0,0 +1,10 @@
|
|||||||
|
prebuilt_jar(
|
||||||
|
name = 'jackson',
|
||||||
|
binary_jar = 'jackson-2.2.3.jar',
|
||||||
|
deps = [
|
||||||
|
'//dependencies/java/guava:guava',
|
||||||
|
],
|
||||||
|
visibility = [
|
||||||
|
'PUBLIC',
|
||||||
|
]
|
||||||
|
)
|
Binary file not shown.
@ -0,0 +1,8 @@
|
|||||||
|
prebuilt_jar(
|
||||||
|
name = 'jsr-305',
|
||||||
|
binary_jar = 'jsr305.jar',
|
||||||
|
source_jar = 'jsr305-src.jar',
|
||||||
|
visibility = [
|
||||||
|
'PUBLIC',
|
||||||
|
],
|
||||||
|
)
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1,7 @@
|
|||||||
|
prebuilt_jar(
|
||||||
|
name = 'jsr-330',
|
||||||
|
binary_jar = 'javax.inject.jar',
|
||||||
|
visibility = [
|
||||||
|
'PUBLIC',
|
||||||
|
],
|
||||||
|
)
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1,7 @@
|
|||||||
|
prebuilt_jar(
|
||||||
|
name = 'sun-tools',
|
||||||
|
binary_jar = 'tools.jar',
|
||||||
|
visibility = [
|
||||||
|
'PUBLIC'
|
||||||
|
]
|
||||||
|
)
|
Binary file not shown.
@ -0,0 +1,2 @@
|
|||||||
|
Ocamldot was written by Trevor Jim. It is in the public domain; use
|
||||||
|
it however you like, at your own risk.
|
@ -0,0 +1,28 @@
|
|||||||
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
#
|
||||||
|
# This source code is licensed under the MIT license found in the
|
||||||
|
# LICENSE file in the root directory of this source tree.
|
||||||
|
|
||||||
|
# Try to automatically guess whether we are running under Windows.
|
||||||
|
# Set WIN32=true manually if this doesn't work.
|
||||||
|
#
|
||||||
|
ifeq (${OSTYPE},cygwin32) # Cygwin Beta 19
|
||||||
|
WIN32=true
|
||||||
|
else
|
||||||
|
ifeq (${OSTYPE},cygwin) # Cygwin Beta 20
|
||||||
|
WIN32=true
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifdef WIN32
|
||||||
|
EXE=.exe
|
||||||
|
else # UNIX
|
||||||
|
EXE=
|
||||||
|
endif
|
||||||
|
|
||||||
|
ocamldot$(EXE): ocamldot.mll
|
||||||
|
ocamllex ocamldot.mll
|
||||||
|
ocamlc -o $@ ocamldot.ml
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) ocamldot$(EXE) ocamldot.ml *.cmi *.cmo *.o *.obj
|
@ -0,0 +1,34 @@
|
|||||||
|
Ocamldot generates program dependency graphs for ocaml programs.
|
||||||
|
|
||||||
|
The dependency graph output by ocamldot can be rendered by a separate
|
||||||
|
program, dot. Dot is freely available from
|
||||||
|
|
||||||
|
http://www.research.att.com/sw/tools/graphviz/
|
||||||
|
|
||||||
|
Ocamldot is designed to process the output of ocamldep. A typical use
|
||||||
|
would be
|
||||||
|
|
||||||
|
ocamldep *.ml | ocamldot > dep.dot
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
ocamldep *.ml > .depend
|
||||||
|
ocamldot .depend > dep.dot
|
||||||
|
|
||||||
|
This will output a dot graph into the file dep.dot. You can then use
|
||||||
|
the program dotty to view, edit, and print the graph.
|
||||||
|
|
||||||
|
Ocamldot has the following options:
|
||||||
|
|
||||||
|
-fullgraph draw the full graph (default is to draw only the kernel)
|
||||||
|
-landscape output in landscape format (default is portrait)
|
||||||
|
-lr draw graph from left to right (default is top to bottom)
|
||||||
|
-r <r> use <r> as a root in the graph; nodes reachable from <r>
|
||||||
|
will be shown
|
||||||
|
|
||||||
|
(The transitive kernel of a dag is the smallest subset of the dag
|
||||||
|
whose transitive closure is the same as the transitive closure of the
|
||||||
|
dag. For example, the kernel of A->B, A->C, B->C is just the two
|
||||||
|
edges A->B, B->C.)
|
||||||
|
|
||||||
|
-Trevor Jim
|
@ -0,0 +1,52 @@
|
|||||||
|
.TH OCAMLDOT 1
|
||||||
|
.SH NAME
|
||||||
|
ocamldot \- generate dependency graphs of ocaml programs
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B ocamldot
|
||||||
|
.I
|
||||||
|
.RI "[options] <dependency-file>"
|
||||||
|
.SH "DESCRIPTION"
|
||||||
|
This manual page documents briefly the
|
||||||
|
.BR ocamldot
|
||||||
|
command.
|
||||||
|
.PP
|
||||||
|
.B ocamldot
|
||||||
|
generates program dependency graphs for ocaml programs. The
|
||||||
|
dependency graph output by ocamldot can be rendered by a separate
|
||||||
|
program, \fIdot\fR.
|
||||||
|
.P
|
||||||
|
Ocamldot is designed to process the output of ocamldep. A typical use would be
|
||||||
|
.P
|
||||||
|
ocamldep *.ml | ocamldot > dep.dot
|
||||||
|
.P
|
||||||
|
or
|
||||||
|
.P
|
||||||
|
ocamldep *.ml > .depend
|
||||||
|
.br
|
||||||
|
ocamldot .depend > dep.dot
|
||||||
|
.SH OPTIONS
|
||||||
|
.TP
|
||||||
|
.B \-fullgraph
|
||||||
|
Draw the full graph (default is to draw only the kernel)
|
||||||
|
.TP
|
||||||
|
.B \-landscape
|
||||||
|
Output in landscape format (default is portrait)
|
||||||
|
.TP
|
||||||
|
.B \-lr
|
||||||
|
Draw graph from left to right (default is top to bottom)
|
||||||
|
.TP
|
||||||
|
.B \-r <r>
|
||||||
|
Use \fI<r>\fR as a root in the graph; nodes reachable from \fI<r>\fR
|
||||||
|
will be shown.
|
||||||
|
.P
|
||||||
|
The transitive kernel of a dag is the smallest subset of the dag whose transitive closure is the same as the transitive closure of the dag.
|
||||||
|
For example, the kernel of A->B, A->C, B->C is just the two edges A->B, B->C.
|
||||||
|
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR ocamldep (1),
|
||||||
|
.BR dot(1)
|
||||||
|
.P
|
||||||
|
\fIhttp://www.research.att.com/~trevor/ocamldot\fR.
|
||||||
|
|
||||||
|
.SH AUTHOR
|
||||||
|
Trevor Jim <trevor@research.att.com>
|
@ -0,0 +1,436 @@
|
|||||||
|
(* ocamldot.mll, July 1999, Trevor Jim *)
|
||||||
|
|
||||||
|
{
|
||||||
|
module StringSet =
|
||||||
|
Set.Make(struct type t = string let compare = compare end)
|
||||||
|
|
||||||
|
module StringMap =
|
||||||
|
Map.Make(struct type t = string let compare = compare end)
|
||||||
|
|
||||||
|
let dependencies = ref []
|
||||||
|
let currentSource = ref ""
|
||||||
|
let addDepend t =
|
||||||
|
let s = !currentSource in
|
||||||
|
if s<>t
|
||||||
|
then dependencies := (s,t)::(!dependencies)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
rule processSource = parse
|
||||||
|
['.' '-' '/' 'A'-'Z' 'a'-'z' '_' '\192'-'\214' '\216'-'\246'
|
||||||
|
'\248'-'\255' '\'' '0'-'9' ]+ '.' ['A'-'Z' 'a'-'z']+
|
||||||
|
[' ' '\009']* ':'
|
||||||
|
{ let s = Lexing.lexeme lexbuf in
|
||||||
|
let i = String.rindex s '.' in
|
||||||
|
let s = String.sub s 0 i in
|
||||||
|
let s = Filename.basename s in
|
||||||
|
let s = String.capitalize s in
|
||||||
|
currentSource := s;
|
||||||
|
processTargets lexbuf }
|
||||||
|
| eof
|
||||||
|
{ () }
|
||||||
|
| _
|
||||||
|
{ processSource lexbuf }
|
||||||
|
|
||||||
|
and processTargets = parse
|
||||||
|
[' ' '\009']+
|
||||||
|
{ processTargets lexbuf }
|
||||||
|
| '\\' [' ' '\009']* ['\010' '\013']+ [' ' '\009']+
|
||||||
|
{ processTargets lexbuf }
|
||||||
|
| ['.' '/' 'A'-'Z' 'a'-'z' '_' '\192'-'\214' '\216'-'\246'
|
||||||
|
'\248'-'\255' '\'' '0'-'9' ]+ '.' ['A'-'Z' 'a'-'z']+
|
||||||
|
{ let t = Lexing.lexeme lexbuf in
|
||||||
|
let i = String.rindex t '.' in
|
||||||
|
let t = String.sub t 0 i in
|
||||||
|
let t = Filename.basename t in
|
||||||
|
let t = String.capitalize t in
|
||||||
|
addDepend t;
|
||||||
|
processTargets lexbuf }
|
||||||
|
| eof
|
||||||
|
{ () }
|
||||||
|
| _
|
||||||
|
{ processSource lexbuf }
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
(********************************)
|
||||||
|
(* Utility functions for graphs *)
|
||||||
|
(********************************)
|
||||||
|
|
||||||
|
|
||||||
|
(**********************************************************************)
|
||||||
|
(* A graph is represented by a (string * StringSet) list, *)
|
||||||
|
(* that is, a list of (source,targets) pairs. *)
|
||||||
|
(**********************************************************************)
|
||||||
|
|
||||||
|
let emptyGraph = []
|
||||||
|
|
||||||
|
(**********************************************************************)
|
||||||
|
(* divideGraph graph source = (sourceTargets, graphWithoutSource) *)
|
||||||
|
(* *)
|
||||||
|
(* Return the targets of a source in a graph and the graph with the *)
|
||||||
|
(* source substracted from the sources. GraphWithoutSources may *)
|
||||||
|
(* still contain source as a target. *)
|
||||||
|
(**********************************************************************)
|
||||||
|
let divideGraph graph source =
|
||||||
|
let rec aux l =
|
||||||
|
match l with
|
||||||
|
[] -> (StringSet.empty,[])
|
||||||
|
| (s,ts)::tl ->
|
||||||
|
if s=source then (ts,tl)
|
||||||
|
else
|
||||||
|
let (sourceTargets,tlWithoutSource) = aux tl in
|
||||||
|
(sourceTargets,(s,ts)::tlWithoutSource) in
|
||||||
|
aux graph
|
||||||
|
|
||||||
|
(*********************************************)
|
||||||
|
(* Add the edge (source,target) to the graph *)
|
||||||
|
(*********************************************)
|
||||||
|
let addEdge graph source target =
|
||||||
|
let (sourceTargets,graphWithoutSource) = divideGraph graph source in
|
||||||
|
(source,StringSet.add target sourceTargets)::graphWithoutSource
|
||||||
|
|
||||||
|
(************************************************************)
|
||||||
|
(* Add the edges { (source,t) | t in targets } to the graph *)
|
||||||
|
(************************************************************)
|
||||||
|
let addEdges graph source targets =
|
||||||
|
let (sourceTargets,graphWithoutSource) = divideGraph graph source in
|
||||||
|
(source,StringSet.union targets sourceTargets)::graphWithoutSource
|
||||||
|
|
||||||
|
(**************************************************)
|
||||||
|
(* Remove the edge (source,target) from the graph *)
|
||||||
|
(**************************************************)
|
||||||
|
let removeEdge graph source target =
|
||||||
|
let rec loop l =
|
||||||
|
match l with
|
||||||
|
[] -> []
|
||||||
|
| (s,ts)::tl ->
|
||||||
|
if s=source
|
||||||
|
then (s,StringSet.remove target ts)::tl
|
||||||
|
else (s,ts)::(loop tl)
|
||||||
|
in loop graph
|
||||||
|
|
||||||
|
(*****************************************************************)
|
||||||
|
(* Remove the edges { (source,t) | t in targets } from the graph *)
|
||||||
|
(*****************************************************************)
|
||||||
|
let removeEdges graph source targets =
|
||||||
|
let rec loop l =
|
||||||
|
match l with
|
||||||
|
[] -> []
|
||||||
|
| (s,ts)::tl ->
|
||||||
|
if s=source
|
||||||
|
then (s,StringSet.diff ts targets)::tl
|
||||||
|
else (s,ts)::(loop tl)
|
||||||
|
in loop graph
|
||||||
|
|
||||||
|
(**********************************************************************)
|
||||||
|
(* Convert between an edge-list representation of graphs and our *)
|
||||||
|
(* representation. *)
|
||||||
|
(**********************************************************************)
|
||||||
|
let edgesOfGraph graph =
|
||||||
|
List.concat
|
||||||
|
(List.map
|
||||||
|
(fun (s,ts) ->
|
||||||
|
List.map (fun t -> (s,t)) (StringSet.elements ts))
|
||||||
|
graph)
|
||||||
|
|
||||||
|
let graphOfEdges edges =
|
||||||
|
List.fold_left
|
||||||
|
(fun g (s,t) -> addEdge g s t)
|
||||||
|
emptyGraph
|
||||||
|
edges
|
||||||
|
|
||||||
|
(****************************)
|
||||||
|
(* Is an edge in the graph? *)
|
||||||
|
(****************************)
|
||||||
|
let isEdge graph source target =
|
||||||
|
try
|
||||||
|
let sourceTargets = List.assoc source graph in
|
||||||
|
StringSet.mem target sourceTargets
|
||||||
|
with Not_found -> false
|
||||||
|
|
||||||
|
(*****************)
|
||||||
|
(* Print a graph *)
|
||||||
|
(*****************)
|
||||||
|
let printGraph graph =
|
||||||
|
let printEdges(source,targets) =
|
||||||
|
StringSet.iter
|
||||||
|
(fun t -> Printf.printf " \"%s\" -> \"%s\" ;\n" source t)
|
||||||
|
targets in
|
||||||
|
List.iter printEdges graph
|
||||||
|
|
||||||
|
(********************************)
|
||||||
|
(* Targets of a node in a graph *)
|
||||||
|
(********************************)
|
||||||
|
let targetsOf graph node = (* A set of nodes *)
|
||||||
|
try List.assoc node graph
|
||||||
|
with Not_found -> StringSet.empty
|
||||||
|
|
||||||
|
(*****************************************)
|
||||||
|
(* Sources that target a node in a graph *)
|
||||||
|
(*****************************************)
|
||||||
|
let sourcesOf graph node = (* A list of nodes *)
|
||||||
|
let rec aux l =
|
||||||
|
match l with
|
||||||
|
[] -> []
|
||||||
|
| (s,ts)::tl ->
|
||||||
|
if StringSet.mem node ts then s::(aux tl)
|
||||||
|
else aux tl in
|
||||||
|
aux graph
|
||||||
|
|
||||||
|
(******************************************************************)
|
||||||
|
(* Add an edge to a transitively closed graph, and return the new *)
|
||||||
|
(* transitive closure. *)
|
||||||
|
(******************************************************************)
|
||||||
|
let addEdgeTc graph source target =
|
||||||
|
let targetTargets = targetsOf graph target in
|
||||||
|
let (sourceTargets,graphWithoutSource) = divideGraph graph source in
|
||||||
|
let sourceSources = sourcesOf graphWithoutSource source in
|
||||||
|
let newSourceTargets =
|
||||||
|
StringSet.add target
|
||||||
|
(StringSet.union sourceTargets targetTargets) in
|
||||||
|
(source,newSourceTargets)::
|
||||||
|
(List.fold_right
|
||||||
|
(fun s g -> addEdges g s newSourceTargets)
|
||||||
|
sourceSources
|
||||||
|
graphWithoutSource)
|
||||||
|
|
||||||
|
(**********************************************************)
|
||||||
|
(* Compute the transitive closure of a graph from scratch *)
|
||||||
|
(**********************************************************)
|
||||||
|
let tc graph =
|
||||||
|
let loop graph (source,targets) =
|
||||||
|
let reachableFromSource =
|
||||||
|
List.fold_left
|
||||||
|
(fun r (s,ts) ->
|
||||||
|
if StringSet.mem s r then StringSet.union r ts
|
||||||
|
else r)
|
||||||
|
targets
|
||||||
|
graph in
|
||||||
|
(source,reachableFromSource)::
|
||||||
|
(List.map
|
||||||
|
(fun (s,ts) ->
|
||||||
|
if StringSet.mem source ts
|
||||||
|
then (s,StringSet.union ts reachableFromSource)
|
||||||
|
else (s,ts))
|
||||||
|
graph) in
|
||||||
|
List.fold_left loop [] graph
|
||||||
|
|
||||||
|
(************************************************************************)
|
||||||
|
(* The transitive kernel (tk) of a dag is a subset of the dag whose *)
|
||||||
|
(* transitive closure is the same as the transitive closure of the dag. *)
|
||||||
|
(* *)
|
||||||
|
(* IF THE GRAPH IS NOT A DAG, THIS CODE WON'T WORK PROPERLY!!! *)
|
||||||
|
(************************************************************************)
|
||||||
|
|
||||||
|
(************************************************************************)
|
||||||
|
(* Add an edge to a kernel dag and return the new kernel and transitive *)
|
||||||
|
(* closure of the new kernel. Requires the transitive closure of the *)
|
||||||
|
(* old kernel. *)
|
||||||
|
(************************************************************************)
|
||||||
|
let addEdgeTk kernel tcKernel source target =
|
||||||
|
if isEdge tcKernel source target
|
||||||
|
then (kernel,tcKernel)
|
||||||
|
else if source=target
|
||||||
|
then (addEdge kernel source target,tcKernel)
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
let (sourceTargets,kernelWithoutSource) = divideGraph kernel source in
|
||||||
|
let targetTargets = StringSet.add target (targetsOf tcKernel target) in
|
||||||
|
let sourceSources = sourcesOf tcKernel source in
|
||||||
|
let kernelWithoutSource =
|
||||||
|
List.fold_left
|
||||||
|
(fun kws s -> removeEdges kws s targetTargets)
|
||||||
|
kernelWithoutSource
|
||||||
|
sourceSources in
|
||||||
|
((source,
|
||||||
|
StringSet.add target
|
||||||
|
(StringSet.diff sourceTargets targetTargets))
|
||||||
|
::kernelWithoutSource,
|
||||||
|
addEdgeTc tcKernel source target)
|
||||||
|
end
|
||||||
|
|
||||||
|
(**********************************)
|
||||||
|
(* The transitive kernel of a dag *)
|
||||||
|
(**********************************)
|
||||||
|
let tk dag =
|
||||||
|
let edges = edgesOfGraph dag in
|
||||||
|
let (kernel,tcKernel) =
|
||||||
|
List.fold_left
|
||||||
|
(fun (k,tck) (s,t) -> addEdgeTk k tck s t)
|
||||||
|
(emptyGraph,emptyGraph)
|
||||||
|
edges in
|
||||||
|
kernel
|
||||||
|
|
||||||
|
(**************************)
|
||||||
|
(* Print the dependencies *)
|
||||||
|
(**************************)
|
||||||
|
let doKernel = ref true
|
||||||
|
let printDepend graph =
|
||||||
|
if (!doKernel) then printGraph (tk graph)
|
||||||
|
else printGraph graph
|
||||||
|
|
||||||
|
let calledOnFile = ref false
|
||||||
|
let getDependFromFile file =
|
||||||
|
calledOnFile := true;
|
||||||
|
try
|
||||||
|
let ic = open_in file in
|
||||||
|
let lexbuf = Lexing.from_channel ic in
|
||||||
|
processSource lexbuf;
|
||||||
|
close_in ic
|
||||||
|
with Sys_error msg -> ()
|
||||||
|
| Exit -> ()
|
||||||
|
let getDependFromStdin () =
|
||||||
|
try
|
||||||
|
let lexbuf = Lexing.from_channel stdin in
|
||||||
|
processSource lexbuf
|
||||||
|
with Sys_error msg -> ()
|
||||||
|
| Exit -> ()
|
||||||
|
|
||||||
|
(**********************************)
|
||||||
|
(* Color and Cluster by directory *)
|
||||||
|
(**********************************)
|
||||||
|
|
||||||
|
let fold_dir f init path =
|
||||||
|
let collect cur_dir path (acum, dirs) =
|
||||||
|
let full_path = Filename.concat cur_dir path in
|
||||||
|
try
|
||||||
|
if Sys.is_directory full_path then
|
||||||
|
(acum, full_path :: dirs)
|
||||||
|
else
|
||||||
|
(f acum full_path, dirs)
|
||||||
|
with Sys_error _ ->
|
||||||
|
(acum, dirs) in
|
||||||
|
let rec fold_dir_ (acum, dirs) =
|
||||||
|
match dirs with
|
||||||
|
| [] ->
|
||||||
|
acum
|
||||||
|
| dir :: dirs ->
|
||||||
|
fold_dir_ (Array.fold_left (fun ad p -> collect dir p ad) (acum, dirs) (Sys.readdir dir)) in
|
||||||
|
if Sys.is_directory path then
|
||||||
|
fold_dir_ (init, [path])
|
||||||
|
else
|
||||||
|
f init path
|
||||||
|
|
||||||
|
let dir_to_mod_names graph dir =
|
||||||
|
let nodes =
|
||||||
|
List.fold_left (fun nodes (source, targets) ->
|
||||||
|
StringSet.add source (StringSet.union targets nodes)
|
||||||
|
) StringSet.empty graph in
|
||||||
|
fold_dir (fun dir_to_mod_names path ->
|
||||||
|
let file = Filename.basename path in
|
||||||
|
let mod_name = String.capitalize (try Filename.chop_extension file with _ -> file) in
|
||||||
|
if ((Filename.check_suffix file ".ml")
|
||||||
|
&& StringSet.mem mod_name nodes)
|
||||||
|
then
|
||||||
|
let dir = Filename.dirname path in
|
||||||
|
let files = mod_name :: (try StringMap.find dir dir_to_mod_names with Not_found -> []) in
|
||||||
|
StringMap.add dir files dir_to_mod_names
|
||||||
|
else
|
||||||
|
dir_to_mod_names
|
||||||
|
) StringMap.empty dir
|
||||||
|
|
||||||
|
let printColors dir_to_mod_names =
|
||||||
|
let num_dirs = StringMap.cardinal dir_to_mod_names in
|
||||||
|
let hsv i s v = Printf.sprintf "\"%f %f %f\"" ((float)i *. (1. /. (float)num_dirs)) s v in
|
||||||
|
StringMap.fold (fun dir mod_names i ->
|
||||||
|
List.iter (fun mod_name ->
|
||||||
|
Printf.printf "\"%s\" [style = filled, fillcolor = %s] ;\n" mod_name (hsv i 0.5 0.9) ;
|
||||||
|
) mod_names ;
|
||||||
|
i + 1
|
||||||
|
) dir_to_mod_names 0
|
||||||
|
|> ignore
|
||||||
|
|
||||||
|
let printClusters clusterDirs dir_to_mod_names =
|
||||||
|
StringMap.iter (fun dir mod_names ->
|
||||||
|
let base = Filename.basename dir in
|
||||||
|
if StringSet.mem base clusterDirs then (
|
||||||
|
Printf.printf "subgraph cluster_%s { label=\"%s\" ;\n" base base;
|
||||||
|
List.iter (fun mod_name ->
|
||||||
|
Printf.printf "\"%s\" ;\n" mod_name
|
||||||
|
) mod_names ;
|
||||||
|
Printf.printf "}\n"
|
||||||
|
)
|
||||||
|
) dir_to_mod_names
|
||||||
|
|
||||||
|
let colorAndCluster clusterDirs graph dir =
|
||||||
|
let dir_to_mod_names = dir_to_mod_names graph dir in
|
||||||
|
printColors dir_to_mod_names ;
|
||||||
|
printClusters clusterDirs dir_to_mod_names
|
||||||
|
|
||||||
|
|
||||||
|
(***************)
|
||||||
|
(* Entry point *)
|
||||||
|
(***************)
|
||||||
|
|
||||||
|
let usage = "Usage: ocamldot [options] <files>"
|
||||||
|
|
||||||
|
let clusters = ref []
|
||||||
|
let leftToRight = ref false
|
||||||
|
let landscape = ref false
|
||||||
|
let roots = ref []
|
||||||
|
;;
|
||||||
|
|
||||||
|
Arg.parse (Arg.align
|
||||||
|
[
|
||||||
|
("-c",
|
||||||
|
Arg.String(fun s -> clusters := s::!clusters),
|
||||||
|
"<c> cluster the modules in the <c> directory in the graph");
|
||||||
|
("-fullgraph",
|
||||||
|
Arg.Clear doKernel,
|
||||||
|
" draw the full graph (default is to draw only the kernel)");
|
||||||
|
("-landscape",
|
||||||
|
Arg.Set landscape,
|
||||||
|
" output in landscape format (default is portrait)");
|
||||||
|
("-lr",
|
||||||
|
Arg.Set leftToRight,
|
||||||
|
" draw graph from left to right (default is top to bottom)");
|
||||||
|
("-r",
|
||||||
|
Arg.String(fun s -> roots := s::!roots),
|
||||||
|
"<r> use <r> as a root in the graph; nodes reachable from <r> will be shown")
|
||||||
|
])
|
||||||
|
getDependFromFile usage;
|
||||||
|
if not(!calledOnFile) then getDependFromStdin();
|
||||||
|
print_string "digraph G {\n";
|
||||||
|
if !landscape
|
||||||
|
then print_string " size=\"10,7.5\" ;\n rotate=90 ;\n"
|
||||||
|
else print_string " size=\"7.5,10\" ;\n";
|
||||||
|
if (!leftToRight) then print_string " rankdir = LR ;\n"
|
||||||
|
else print_string " rankdir = TB ;\n";
|
||||||
|
let graph = graphOfEdges(!dependencies) in
|
||||||
|
begin
|
||||||
|
match !roots with
|
||||||
|
[] -> printDepend graph
|
||||||
|
| roots ->
|
||||||
|
(* Set up the graph so that the roots are printed at the same level *)
|
||||||
|
print_string " { rank=same ;\n";
|
||||||
|
List.iter
|
||||||
|
(fun r ->
|
||||||
|
print_string " ";
|
||||||
|
print_string r;
|
||||||
|
print_string " ;\n")
|
||||||
|
roots;
|
||||||
|
print_string " };\n";
|
||||||
|
(* Find the graph reachable from the roots *)
|
||||||
|
let tcGraph = tc graph in
|
||||||
|
let reachable node =
|
||||||
|
(List.exists (fun r -> r=node) roots)
|
||||||
|
||
|
||||||
|
(List.exists (fun r -> isEdge tcGraph r node) roots) in
|
||||||
|
let reachableFromRoots =
|
||||||
|
List.concat
|
||||||
|
(List.map
|
||||||
|
(fun (source,targets) ->
|
||||||
|
if reachable source
|
||||||
|
then [(source,targets)]
|
||||||
|
else [])
|
||||||
|
graph) in
|
||||||
|
printDepend reachableFromRoots;
|
||||||
|
let clusterDirs = List.fold_left (fun z s -> StringSet.add s z) StringSet.empty !clusters in
|
||||||
|
colorAndCluster clusterDirs reachableFromRoots (Sys.getcwd ())
|
||||||
|
end;
|
||||||
|
print_string "}\n";
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
FROM debian:bullseye-slim
|
||||||
|
|
||||||
|
LABEL maintainer "Infer team"
|
||||||
|
|
||||||
|
# mkdir the man/man1 directory due to Debian bug #863199
|
||||||
|
RUN apt-get update && \
|
||||||
|
mkdir -p /usr/share/man/man1 && \
|
||||||
|
apt-get install --yes --no-install-recommends \
|
||||||
|
curl \
|
||||||
|
libc6-dev \
|
||||||
|
openjdk-11-jdk-headless \
|
||||||
|
sqlite3 \
|
||||||
|
xz-utils \
|
||||||
|
zlib1g-dev && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Download the Infer release
|
||||||
|
RUN INFER_VERSION=v1.1.0; \
|
||||||
|
cd /opt && \
|
||||||
|
curl -sL \
|
||||||
|
https://github.com/facebook/infer/releases/download/${INFER_VERSION}/infer-linux64-${INFER_VERSION}.tar.xz | \
|
||||||
|
tar xJ && \
|
||||||
|
rm -f /infer && \
|
||||||
|
ln -s ${PWD}/infer-linux64-$INFER_VERSION /infer
|
||||||
|
|
||||||
|
# Install infer
|
||||||
|
ENV PATH /infer/bin:${PATH}
|
@ -0,0 +1,37 @@
|
|||||||
|
# docker images for Infer
|
||||||
|
|
||||||
|
This directory, `docker/` inside the Infer repo,
|
||||||
|
contains a docker file to install Infer within a
|
||||||
|
[docker](https://www.docker.com/) container. This can be used to
|
||||||
|
quickly try Infer or to deploy Infer.
|
||||||
|
|
||||||
|
|
||||||
|
## Pre-requisites
|
||||||
|
|
||||||
|
To use this docker image, you will need a working docker
|
||||||
|
installation. See the instructions for
|
||||||
|
[Linux](http://docs.docker.com/linux/step_one/) or
|
||||||
|
[MacOSX](http://docs.docker.com/mac/step_one/) as appropriate.
|
||||||
|
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
|
||||||
|
This docker file will use the latest
|
||||||
|
[released](https://github.com/facebook/infer/releases) version of
|
||||||
|
Infer.
|
||||||
|
|
||||||
|
1. Get docker running, e.g. using Docker Quickstart Terminal.
|
||||||
|
2. go to the version of your choice, e.g. `cd docker/1.1.0/`
|
||||||
|
3. Build or install Infer in the Docker container and try on an example:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd docker/1.1.0/
|
||||||
|
docker build -t infer .
|
||||||
|
# mount the local examples directory inside the image
|
||||||
|
# you can mount your project directory here instead
|
||||||
|
docker run -it infer -v $PWD/../../examples:/infer-examples /bin/bash
|
||||||
|
# you should now be inside the docker container with a shell prompt, e.g.
|
||||||
|
# "root@5c3b9af90d59:/# "
|
||||||
|
cd /infer-examples/
|
||||||
|
infer -- clang -c hello.c
|
||||||
|
```
|
@ -0,0 +1,69 @@
|
|||||||
|
FROM debian:bullseye-slim AS compilator
|
||||||
|
|
||||||
|
LABEL maintainer "Infer team"
|
||||||
|
|
||||||
|
# mkdir the man/man1 directory due to Debian bug #863199
|
||||||
|
RUN apt-get update && \
|
||||||
|
mkdir -p /usr/share/man/man1 && \
|
||||||
|
apt-get install --yes --no-install-recommends \
|
||||||
|
autoconf \
|
||||||
|
automake \
|
||||||
|
bzip2 \
|
||||||
|
cmake \
|
||||||
|
curl \
|
||||||
|
g++ \
|
||||||
|
gcc \
|
||||||
|
git \
|
||||||
|
libc6-dev \
|
||||||
|
libgmp-dev \
|
||||||
|
libmpfr-dev \
|
||||||
|
libsqlite3-dev \
|
||||||
|
make \
|
||||||
|
opam \
|
||||||
|
openjdk-11-jdk-headless \
|
||||||
|
patch \
|
||||||
|
patchelf \
|
||||||
|
pkg-config \
|
||||||
|
python3 \
|
||||||
|
python3-distutils \
|
||||||
|
unzip \
|
||||||
|
xz-utils \
|
||||||
|
zlib1g-dev && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Disable sandboxing
|
||||||
|
# Without this opam fails to compile OCaml for some reason. We don't need sandboxing inside a Docker container anyway.
|
||||||
|
RUN opam init --reinit --bare --disable-sandboxing --yes --auto-setup
|
||||||
|
|
||||||
|
# Download the latest Infer master
|
||||||
|
RUN cd / && \
|
||||||
|
git clone --depth 1 https://github.com/facebook/infer/
|
||||||
|
|
||||||
|
# Build opam deps first, then infer. This way if any step fails we
|
||||||
|
# don't lose the significant amount of work done in the previous
|
||||||
|
# steps.
|
||||||
|
RUN cd /infer && ./build-infer.sh java --only-setup-opam
|
||||||
|
RUN cd /infer && ./build-infer.sh java
|
||||||
|
|
||||||
|
# Generate a release
|
||||||
|
RUN cd /infer && \
|
||||||
|
make install-with-libs \
|
||||||
|
BUILD_MODE=opt \
|
||||||
|
PATCHELF=patchelf \
|
||||||
|
DESTDIR="/infer-release" \
|
||||||
|
libdir_relative_to_bindir="../lib"
|
||||||
|
|
||||||
|
FROM debian:buster-slim AS executor
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install --yes --no-install-recommends sqlite3
|
||||||
|
|
||||||
|
# Get the infer release
|
||||||
|
COPY --from=compilator /infer-release/usr/local /infer
|
||||||
|
|
||||||
|
# Install infer
|
||||||
|
ENV PATH /infer/bin:${PATH}
|
||||||
|
|
||||||
|
# if called with /infer-host mounted then copy infer there
|
||||||
|
RUN if test -d /infer-host; then \
|
||||||
|
cp -av /infer/. /infer-host; \
|
||||||
|
fi
|
@ -0,0 +1,74 @@
|
|||||||
|
FROM debian:bullseye-slim AS compilator
|
||||||
|
|
||||||
|
LABEL maintainer "Infer team"
|
||||||
|
|
||||||
|
# mkdir the man/man1 directory due to Debian bug #863199
|
||||||
|
RUN apt-get update && \
|
||||||
|
mkdir -p /usr/share/man/man1 && \
|
||||||
|
apt-get install --yes --no-install-recommends \
|
||||||
|
autoconf \
|
||||||
|
automake \
|
||||||
|
bubblewrap \
|
||||||
|
bzip2 \
|
||||||
|
cmake \
|
||||||
|
curl \
|
||||||
|
g++ \
|
||||||
|
gcc \
|
||||||
|
git \
|
||||||
|
libc6-dev \
|
||||||
|
libgmp-dev \
|
||||||
|
libmpfr-dev \
|
||||||
|
libsqlite3-dev \
|
||||||
|
make \
|
||||||
|
opam \
|
||||||
|
openjdk-11-jdk-headless \
|
||||||
|
patch \
|
||||||
|
patchelf \
|
||||||
|
pkg-config \
|
||||||
|
python3 \
|
||||||
|
python3-distutils \
|
||||||
|
unzip \
|
||||||
|
xz-utils \
|
||||||
|
zlib1g-dev && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Disable sandboxing
|
||||||
|
# Without this opam fails to compile OCaml for some reason. We don't need sandboxing inside a Docker container anyway.
|
||||||
|
RUN opam init --reinit --bare --disable-sandboxing --yes --auto-setup
|
||||||
|
|
||||||
|
# Download the latest Infer master
|
||||||
|
RUN cd / && \
|
||||||
|
git clone --depth 1 https://github.com/facebook/infer/
|
||||||
|
|
||||||
|
# Build opam deps first, then clang, then infer. This way if any step
|
||||||
|
# fails we don't lose the significant amount of work done in the
|
||||||
|
# previous steps.
|
||||||
|
RUN cd /infer && ./build-infer.sh --only-setup-opam
|
||||||
|
RUN cd /infer && \
|
||||||
|
eval $(opam env) && \
|
||||||
|
./autogen.sh && \
|
||||||
|
./configure && \
|
||||||
|
./facebook-clang-plugins/clang/setup.sh
|
||||||
|
|
||||||
|
# Generate a release
|
||||||
|
RUN cd /infer && \
|
||||||
|
make install-with-libs \
|
||||||
|
BUILD_MODE=opt \
|
||||||
|
PATCHELF=patchelf \
|
||||||
|
DESTDIR="/infer-release" \
|
||||||
|
libdir_relative_to_bindir="../lib"
|
||||||
|
|
||||||
|
FROM debian:buster-slim AS executor
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install --yes --no-install-recommends sqlite3
|
||||||
|
|
||||||
|
# Get the infer release
|
||||||
|
COPY --from=compilator /infer-release/usr/local /infer
|
||||||
|
|
||||||
|
# Install infer
|
||||||
|
ENV PATH /infer/bin:${PATH}
|
||||||
|
|
||||||
|
# if called with /infer-host mounted then copy infer there
|
||||||
|
RUN if test -d /infer-host; then \
|
||||||
|
cp -av /infer/. /infer-host; \
|
||||||
|
fi
|
@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Hello {
|
||||||
|
int test() {
|
||||||
|
String s = null;
|
||||||
|
return s.length();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@interface Hello : NSObject
|
||||||
|
@property NSString* s;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation Hello
|
||||||
|
NSString* m() {
|
||||||
|
Hello* hello = nil;
|
||||||
|
return hello->_s;
|
||||||
|
}
|
||||||
|
@end
|
@ -0,0 +1,41 @@
|
|||||||
|
This directory contains small examples to play with Infer. They each exhibit
|
||||||
|
one simple programming error that is caught by Infer.
|
||||||
|
|
||||||
|
Contents
|
||||||
|
--------
|
||||||
|
|
||||||
|
- `Hello.java`: try this example by running
|
||||||
|
```infer -- javac Hello.java ```
|
||||||
|
|
||||||
|
- `Hello.m`: try this example by running
|
||||||
|
```infer -- clang -c Hello.m```
|
||||||
|
|
||||||
|
- `hello.c`: try this example by running
|
||||||
|
```infer -- gcc -c hello.c```
|
||||||
|
|
||||||
|
In this case, note that Infer captures the gcc command and runs
|
||||||
|
clang instead to parse C files. Thus you may get compiler errors and
|
||||||
|
warnings that differ from gcc's.
|
||||||
|
|
||||||
|
- `android_hello/`: a sample Android app. Try this example by running
|
||||||
|
```infer -- ./gradlew build```
|
||||||
|
|
||||||
|
Make sure that you have the Android SDK 22 installed and up to date, and in
|
||||||
|
particular the "Android SDK Build-tools" and "Android Support Repository".
|
||||||
|
|
||||||
|
- `c_hello/`: a sample make-based C project. Try this example by running
|
||||||
|
```infer -- make```
|
||||||
|
|
||||||
|
- `ios_hello/`: a sample iOS app. Try this example by running
|
||||||
|
```infer -- xcodebuild -target HelloWorldApp -configuration Debug -sdk iphonesimulator```
|
||||||
|
|
||||||
|
- `java_hello/`: a sample Java project. Try this example by running
|
||||||
|
```infer -- javac Pointers.java Resources.java Hello.java```
|
||||||
|
|
||||||
|
Note
|
||||||
|
----
|
||||||
|
|
||||||
|
The infer toplevel command must be in your PATH for the commands above to
|
||||||
|
succeed. Otherwise, modify the commands to use the correct path to infer, eg
|
||||||
|
```../infer/bin/infer -- javac Hello.java```
|
||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
../../.inferconfig
|
@ -0,0 +1 @@
|
|||||||
|
/build
|
@ -0,0 +1,27 @@
|
|||||||
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 22
|
||||||
|
buildToolsVersion "22.0.1"
|
||||||
|
|
||||||
|
lintOptions.abortOnError false
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
applicationId "infer.inferandroidexample"
|
||||||
|
minSdkVersion 8
|
||||||
|
targetSdkVersion 22
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
}
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
compile 'com.android.support:appcompat-v7:22.0.0'
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# By default, the flags in this file are appended to flags specified
|
||||||
|
# in /Users/irp/android-sdk-macosx/tools/proguard/proguard-android.txt
|
||||||
|
# You can edit the include path and order by changing the proguardFiles
|
||||||
|
# directive in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# Add any project specific keep options here:
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package infer.inferandroidexample;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
import android.test.ApplicationTestCase;
|
||||||
|
|
||||||
|
/** <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a> */
|
||||||
|
public class ApplicationTest extends ApplicationTestCase<Application> {
|
||||||
|
public ApplicationTest() {
|
||||||
|
super(Application.class);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="infer.inferandroidexample" >
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:icon="@drawable/ic_launcher"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:theme="@style/AppTheme" >
|
||||||
|
<activity
|
||||||
|
android:name=".MainActivity"
|
||||||
|
android:label="@string/app_name" >
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// _SHOULD_BE_SKIPPED_
|
||||||
|
|
||||||
|
package infer.inferandroidexample;
|
||||||
|
|
||||||
|
public class Generated {
|
||||||
|
|
||||||
|
static Object returnsNull() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package infer.inferandroidexample;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.app.ActionBarActivity;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
public class MainActivity extends ActionBarActivity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_main);
|
||||||
|
String s = getDay();
|
||||||
|
int length = s.length();
|
||||||
|
writeToFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getDay() {
|
||||||
|
if (Calendar.getInstance().get(Calendar.DAY_OF_WEEK) == Calendar.WEDNESDAY) {
|
||||||
|
return "Wednesday";
|
||||||
|
} else {
|
||||||
|
return otherOutput();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String otherOutput() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeToFile() {
|
||||||
|
byte[] arr = {1, 2, 3};
|
||||||
|
FileOutputStream fis;
|
||||||
|
try {
|
||||||
|
fis = new FileOutputStream("file.txt");
|
||||||
|
fis.write(arr);
|
||||||
|
fis.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
// Deal with exception
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
// Inflate the menu; this adds items to the action bar if it is present.
|
||||||
|
getMenuInflater().inflate(R.menu.menu_main, menu);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
// Handle action bar item clicks here. The action bar will
|
||||||
|
// automatically handle clicks on the Home/Up button, so long
|
||||||
|
// as you specify a parent activity in AndroidManifest.xml.
|
||||||
|
int id = item.getItemId();
|
||||||
|
|
||||||
|
//noinspection SimplifiableIfStatement
|
||||||
|
if (id == R.id.action_settings) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void inferShouldNotReport() {
|
||||||
|
// Generated.java is supposed to be skipped by infer, thus even though
|
||||||
|
// Generated.returnsNull() returns null, infer is not supposed to know
|
||||||
|
// about it hence should not report an NPE here
|
||||||
|
Object o = Generated.returnsNull();
|
||||||
|
o.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package infer.other;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.app.ActionBarActivity;
|
||||||
|
|
||||||
|
public class MainActivity extends ActionBarActivity {
|
||||||
|
|
||||||
|
Object source() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
source().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NULL_DEREFERENCE")
|
||||||
|
void shouldNotBeReported() {
|
||||||
|
source().toString();
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 9.2 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 19 KiB |
@ -0,0 +1,11 @@
|
|||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingTop="@dimen/activity_vertical_margin"
|
||||||
|
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
|
||||||
|
|
||||||
|
<TextView android:text="@string/hello_world" android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
@ -0,0 +1,6 @@
|
|||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
|
||||||
|
<item android:id="@+id/action_settings" android:title="@string/action_settings"
|
||||||
|
android:orderInCategory="100" app:showAsAction="never" />
|
||||||
|
</menu>
|
@ -0,0 +1,6 @@
|
|||||||
|
<resources>
|
||||||
|
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
|
||||||
|
(such as screen margins) for screens with more than 820dp of available width. This
|
||||||
|
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
|
||||||
|
<dimen name="activity_horizontal_margin">64dp</dimen>
|
||||||
|
</resources>
|
@ -0,0 +1,5 @@
|
|||||||
|
<resources>
|
||||||
|
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||||
|
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||||
|
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||||
|
</resources>
|
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<string name="app_name">InferAndroidExample</string>
|
||||||
|
<string name="hello_world">Hello world!</string>
|
||||||
|
<string name="action_settings">Settings</string>
|
||||||
|
|
||||||
|
</resources>
|
@ -0,0 +1,8 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<!-- Base application theme. -->
|
||||||
|
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||||
|
<!-- Customize your theme here. -->
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</resources>
|
@ -0,0 +1,19 @@
|
|||||||
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
|
||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath 'com.android.tools.build:gradle:2.2.3'
|
||||||
|
|
||||||
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
|
// in the individual module build.gradle files
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
repositories {
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
# Project-wide Gradle settings.
|
||||||
|
|
||||||
|
# IDE (e.g. Android Studio) users:
|
||||||
|
# Gradle settings configured through the IDE *will override*
|
||||||
|
# any settings specified in this file.
|
||||||
|
|
||||||
|
# For more details on how to configure your build environment visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||||
|
|
||||||
|
# Specifies the JVM arguments used for the daemon process.
|
||||||
|
# The setting is particularly useful for tweaking memory settings.
|
||||||
|
# Default value: -Xmx10248m -XX:MaxPermSize=256m
|
||||||
|
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||||
|
|
||||||
|
# When configured, Gradle will run in incubating parallel mode.
|
||||||
|
# This option should only be used with decoupled projects. More details, visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||||
|
# org.gradle.parallel=true
|
Binary file not shown.
@ -0,0 +1,6 @@
|
|||||||
|
#Wed Apr 10 15:27:10 PDT 2013
|
||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-3.4-bin.zip
|
@ -0,0 +1,164 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##
|
||||||
|
## Gradle start up script for UN*X
|
||||||
|
##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS=""
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn ( ) {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die ( ) {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# For Cygwin, ensure paths are in UNIX format before anything is touched.
|
||||||
|
if $cygwin ; then
|
||||||
|
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >&-
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >&-
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="java"
|
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||||
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
ulimit -n $MAX_FD
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
|
if $darwin; then
|
||||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
|
if $cygwin ; then
|
||||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
|
||||||
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
SEP=""
|
||||||
|
for dir in $ROOTDIRSRAW ; do
|
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
|
SEP="|"
|
||||||
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=$((i+1))
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
(0) set -- ;;
|
||||||
|
(1) set -- "$args0" ;;
|
||||||
|
(2) set -- "$args0" "$args1" ;;
|
||||||
|
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||||
|
function splitJvmOpts() {
|
||||||
|
JVM_OPTS=("$@")
|
||||||
|
}
|
||||||
|
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||||
|
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||||
|
|
||||||
|
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
@ -0,0 +1 @@
|
|||||||
|
include ':app'
|
@ -0,0 +1,15 @@
|
|||||||
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
#
|
||||||
|
# This source code is licensed under the MIT license found in the
|
||||||
|
# LICENSE file in the root directory of this source tree.
|
||||||
|
|
||||||
|
SOURCES = $(shell ls *.c)
|
||||||
|
OBJECTS = $(SOURCES:.c=.o)
|
||||||
|
|
||||||
|
all: $(OBJECTS)
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
${CC} -c $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(OBJECTS)
|
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
struct Person {
|
||||||
|
int age;
|
||||||
|
int height;
|
||||||
|
int weight;
|
||||||
|
};
|
||||||
|
|
||||||
|
int simple_null_pointer() {
|
||||||
|
struct Person* max = 0;
|
||||||
|
return max->age;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Person* Person_create(int age, int height, int weight) {
|
||||||
|
struct Person* who = 0;
|
||||||
|
return who;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_age(struct Person* who) { return who->age; }
|
||||||
|
|
||||||
|
int null_pointer_interproc() {
|
||||||
|
struct Person* joe = Person_create(32, 64, 140);
|
||||||
|
return get_age(joe);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fileNotClosed() {
|
||||||
|
int fd = open("hi.txt", O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||||||
|
if (fd != -1) {
|
||||||
|
char buffer[256];
|
||||||
|
// We can easily batch that by separating with space
|
||||||
|
write(fd, buffer, strlen(buffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void simple_leak() {
|
||||||
|
int* p;
|
||||||
|
p = (int*)malloc(sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_realloc_leak() {
|
||||||
|
int *p, *q;
|
||||||
|
p = (int*)malloc(sizeof(int));
|
||||||
|
q = (int*)realloc(p, sizeof(int) * 42);
|
||||||
|
// if realloc fails, then p becomes unreachable
|
||||||
|
if (q != NULL)
|
||||||
|
free(q);
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
#
|
||||||
|
# This source code is licensed under the MIT license found in the
|
||||||
|
# LICENSE file in the root directory of this source tree.
|
||||||
|
|
||||||
|
SOURCES = simple_null.cpp
|
||||||
|
OBJECTS = $(SOURCES:.cpp=.o)
|
||||||
|
|
||||||
|
all: $(OBJECTS)
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
${CC} -c $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(OBJECTS)
|
@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
void deref_null() {
|
||||||
|
int* p = nullptr;
|
||||||
|
*p = 42;
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
#
|
||||||
|
# This source code is licensed under the MIT license found in the
|
||||||
|
# LICENSE file in the root directory of this source tree.
|
||||||
|
|
||||||
|
SOURCES = simple_null_interproc.c wrappers.c
|
||||||
|
OBJECTS = $(SOURCES:.c=.o)
|
||||||
|
|
||||||
|
all: $(OBJECTS)
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
${CC} -c $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(OBJECTS)
|
@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int* allocate_int();
|
||||||
|
void set(int* p, int value);
|
||||||
|
|
||||||
|
void deref_null() {
|
||||||
|
int* p = allocate_int();
|
||||||
|
set(p, 42);
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int* allocate_int();
|
||||||
|
void set(int* p, int value);
|
||||||
|
|
||||||
|
void deref_null_ok() {
|
||||||
|
int* p = allocate_int();
|
||||||
|
if (p != NULL) {
|
||||||
|
set(p, 42);
|
||||||
|
}
|
||||||
|
free(p);
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int* allocate_int() { return malloc(sizeof(int)); }
|
||||||
|
|
||||||
|
void set(int* p, int value) { *p = value; }
|
@ -0,0 +1,15 @@
|
|||||||
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
#
|
||||||
|
# This source code is licensed under the MIT license found in the
|
||||||
|
# LICENSE file in the root directory of this source tree.
|
||||||
|
|
||||||
|
SOURCES = Resources.java
|
||||||
|
OBJECT = Resources.class
|
||||||
|
|
||||||
|
all: $(OBJECT)
|
||||||
|
|
||||||
|
$(OBJECT): $(SOURCES)
|
||||||
|
javac $^
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(OBJECT)
|
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
class Resources {
|
||||||
|
|
||||||
|
public static void cat() throws IOException {
|
||||||
|
FileInputStream infile = null;
|
||||||
|
FileOutputStream outfile = null;
|
||||||
|
try {
|
||||||
|
infile = new FileInputStream(new File("infile.txt"));
|
||||||
|
outfile = new FileOutputStream(new File("outfile.txt"));
|
||||||
|
outfile.write(infile.read());
|
||||||
|
} finally {
|
||||||
|
if (infile != null) infile.close();
|
||||||
|
if (outfile != null) outfile.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class ResourcesFixed {
|
||||||
|
|
||||||
|
public static void cat() throws IOException {
|
||||||
|
try (FileInputStream infile = new FileInputStream(new File("infile.txt"));
|
||||||
|
FileOutputStream outfile = new FileOutputStream(new File("outfile.txt")); ) {
|
||||||
|
outfile.write(infile.read());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@ThreadSafe
|
||||||
|
public interface Account {
|
||||||
|
void deposit(int amount);
|
||||||
|
|
||||||
|
int withdraw(int amount);
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class AccountImplementation implements Account {
|
||||||
|
|
||||||
|
int mBalance = 0;
|
||||||
|
|
||||||
|
private void addToBalance(int amount) {
|
||||||
|
mBalance += amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void deposit(int amount) {
|
||||||
|
if (amount > 0) {
|
||||||
|
addToBalance(amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized int withdraw(int amount) {
|
||||||
|
if (amount >= 0 && mBalance - amount >= 0) {
|
||||||
|
addToBalance(-amount);
|
||||||
|
return mBalance;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
@ThreadSafe
|
||||||
|
public class Client {
|
||||||
|
|
||||||
|
Account account;
|
||||||
|
|
||||||
|
void getPaid(int amount) {
|
||||||
|
account.deposit(amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
int buyCoffee() {
|
||||||
|
return account.withdraw(5);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
#
|
||||||
|
# This source code is licensed under the MIT license found in the
|
||||||
|
# LICENSE file in the root directory of this source tree.
|
||||||
|
|
||||||
|
SOURCES = Account.java AccountImplementation.java Client.java
|
||||||
|
OBJECT = Client.class
|
||||||
|
|
||||||
|
all: $(OBJECT)
|
||||||
|
|
||||||
|
$(OBJECT): $(SOURCES)
|
||||||
|
javac $^
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(OBJECT)
|
@ -0,0 +1,7 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
public @interface ThreadSafe {}
|
@ -0,0 +1,11 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
public interface Account {
|
||||||
|
void deposit(int amount);
|
||||||
|
|
||||||
|
int withdraw(int amount);
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class AccountImplementation implements Account {
|
||||||
|
|
||||||
|
int mBalance = 0;
|
||||||
|
|
||||||
|
private void addToBalance(int amount) {
|
||||||
|
mBalance += amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deposit(int amount) {
|
||||||
|
if (amount > 0) {
|
||||||
|
addToBalance(amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int withdraw(int amount) {
|
||||||
|
if (amount >= 0 && mBalance - amount >= 0) {
|
||||||
|
addToBalance(-amount);
|
||||||
|
return mBalance;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
public class Client {
|
||||||
|
|
||||||
|
Account account;
|
||||||
|
|
||||||
|
void getPaid(int amount) {
|
||||||
|
account.deposit(amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
int buyCoffee() {
|
||||||
|
return account.withdraw(5);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
#
|
||||||
|
# This source code is licensed under the MIT license found in the
|
||||||
|
# LICENSE file in the root directory of this source tree.
|
||||||
|
|
||||||
|
SOURCES = Account.java AccountImplementation.java Client.java
|
||||||
|
OBJECT = Client.class
|
||||||
|
|
||||||
|
all: $(OBJECT)
|
||||||
|
|
||||||
|
$(OBJECT): $(SOURCES)
|
||||||
|
javac $^
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(OBJECT)
|
@ -0,0 +1,7 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
public @interface ThreadSafe {}
|
@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Client<T> {
|
||||||
|
|
||||||
|
String foo() {
|
||||||
|
Library<T> lib = new Library<T>();
|
||||||
|
T t = lib.get();
|
||||||
|
return t == null ? "default" : t.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Library<T> {
|
||||||
|
|
||||||
|
@Nullable T t;
|
||||||
|
|
||||||
|
private native @Nullable T mayReturnNull();
|
||||||
|
|
||||||
|
public Library() {
|
||||||
|
t = mayReturnNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public T get() {
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
#
|
||||||
|
# This source code is licensed under the MIT license found in the
|
||||||
|
# LICENSE file in the root directory of this source tree.
|
||||||
|
|
||||||
|
SOURCES = Client.java Library.java
|
||||||
|
OBJECT = Client.class
|
||||||
|
|
||||||
|
all: $(OBJECT)
|
||||||
|
|
||||||
|
$(OBJECT): $(SOURCES)
|
||||||
|
javac $^
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(OBJECT)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue