{"id":16885762,"url":"https://github.com/filmil/clang-tool-example","last_synced_at":"2025-03-20T06:15:08.614Z","repository":{"id":145211526,"uuid":"382456412","full_name":"filmil/clang-tool-example","owner":"filmil","description":"An example C++ code analysis tool linked against the respective clang and LLVM libraries, but built out of the llvm project code tree","archived":false,"fork":false,"pushed_at":"2021-07-02T20:42:56.000Z","size":10,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-01-25T07:28:34.315Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"CMake","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/filmil.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-07-02T20:27:30.000Z","updated_at":"2021-07-02T20:42:58.000Z","dependencies_parsed_at":null,"dependency_job_id":"c58a7c09-7ab9-41ba-99c3-fa3c78c62ab2","html_url":"https://github.com/filmil/clang-tool-example","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/filmil%2Fclang-tool-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/filmil%2Fclang-tool-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/filmil%2Fclang-tool-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/filmil%2Fclang-tool-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/filmil","download_url":"https://codeload.github.com/filmil/clang-tool-example/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244560392,"owners_count":20472220,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-13T16:36:55.434Z","updated_at":"2025-03-20T06:15:08.609Z","avatar_url":"https://github.com/filmil.png","language":"CMake","funding_links":[],"categories":[],"sub_categories":[],"readme":"# An example tool built against LLVM 13.\n\nI wanted to make a clang tool out of the `clang` source code tree.  Ostensibly\nthere are examples to follow.  However, I found out that the examples are based\non the assumption that you are writing a tool in the llvm project tree, which I\ndidn't want to do: I don't want to argue my use of the tool I want to make with\nsomeone who has zero interest in actually seeing my thing get done.  I, on the\nother hand, do need to get my thing working.\n\nHere is the inventory of examples that I found on the Internet:\n\n* https://github.com/peter-can-talk/cppnow-2017 has bitrotted.  The docker\n  approach has merit since you get to burn your environment into an image; but\n  the API has changed since the thing was made, and I wanted to have something\n  that works *now*. So...\n    \n* https://github.com/firolino/clang-tool/ was promising, but requires a system\n  clang installation, which is a nonstarter since I want to build on multiple\n  machines, and it is very hard to guarantee you'd be using the same library\n  version if you use the library installation as provided by the system. I\n  don't want to fight the package system on my machine to compile things.\n\n* https://github.com/google/llvm-bazel is purportedly a `bazel` configuration\n  for building with llvm. Of course it does not work on many levels. At this\n  point nothing about `bazel` not working out of the box surprises me.\n\n* This [mailing list discussion][1] has links to all the bitrotted examples.\n\n[1]: http://clang-developers.42468.n3.nabble.com/How-to-build-a-clang-tool-out-of-the-build-tree-td4066632.html\n\n## What to do?\n\nI found [this blog post][hee] that got me mostly on the right track.  It is old, however,\nso some of the concerns there no longer apply, and the API has also bitrotted.\n\n[hee]: https://heejune.me/2016/08/17/build-your-own-clang-example-outside-of-the-llvm-source-tree/\n\n## Building and installing `clang` and `llvm`\n\nI decided to use `ninja` to build LLVM since I have access to a 48-core machine\nand wanted to make use of all that CPU automatically.\n\n### Preparation\n\n* Make sure you have either GCC or clang installed to compile the program, as\n  well as a working build environment.\n\n* Get and install `ninja`.  I like building from source so I checked it out from\n  source and installed, as described [here][ninja].\n\n[ninja]: https://ninja-build.org\n\n* Get the `llvm` source code, as described [here][install].  I like keeping build,\n  install and source directories separate so I roughly did this:\n\n  ```bash\n  $ mkdir -p ${HOME}/code/llvm/{build,installation}\n  $ cd ${HOME}/code/llvm\n  $ git clone git@github.com:llvm/llvm-project\n  ```\n\n  The commit ID at which I checked the project out is\n  `c360553c15a8e5aa94d2236eb73e7dfeab9543e5`, in case you are interested in\n  reproducing the build environment exactly.  It matters, because the LLVM APIs\n  change over time, so my example may bitrot as well.  Sigh.\n\n[install]: https://llvm.org/docs/GettingStarted.html#getting-the-source-code-and-building-llvm\n\n### Generating the `ninja` build files\n\nThe command line to generate the `ninja` build files is as follows:\n\n```\ncd ${HOME}/code/llvm/build\ncmake -G Ninja \\\n  -DLLVM_ENABLE_PROJECTS='clang;clang-tools-extra;libcxx;compiler-rt;libcxxabi' \\\n  -DCMAKE_INSTALL_PREFIX=$HOME/code/llvm/installation \\\n  ../llvm-project/llvm\nninja\nninja install\n```\n\nThe build and installation steps tend to last *a long time*.  Luckily, I always\nsaw some sort of a progress indicator which helped reasure me that things are\ngoing as planned.\n\nOnce done, you will have a viable `clang` and `llvm` installation.  \nYou do need to do the last `ninja install` step, it seems: the structure of the\ninstallation directory is very specific, and different from the structure of the\nsource and build dirs.  I thought I'd save some disk space by referring to files\nfrom the source and build directories instead of installing, but that turned out\nto invite more trouble than it was worth.\n\n## Building and installing the example.\n\nFinally, we hopefully get to substance.\n\nI decided to follow the above example and separate the source and build\ndirectories.\n\n```\nmkdir -p ${HOME}/code/clang-tool/build\ncd ${HOME}/code/clang-tool\ngit checkout git@github.com:filmil/clang-tool-example\n```\n\nThis checks out the source code and sets up the build directory.  The file\n[compile.sh] shows you the steps to compile the code.  It is a bit sad that\nit's 2021 and we still don't have a sane way to build softwre and have to\nresort to bash, but what to do.  The source code was taken from the [llvm\nexample][llvmex], which itself bitrotted and does not show a recent API change\nto the needed `CommonOptionsParser` class; so I had to fix it up a tad bit,\nconsulting [llvm source docs][doxygenx].\n\n[doxygenx]: https://clang.llvm.org/doxygen/classclang_1_1tooling_1_1CommonOptionsParser.html\n[llvmex]: https://clang.llvm.org/docs/LibTooling.html\n\nTo compile, do the following:\n\n```\ncd ${HOME}/code/clang-tool/build\n../clang-tool-example/compile.sh\n```\n\nThe script [compile.sh] will configure your build, expose\n`compile_commands.json` in case you use IDE support that is aware of that file,\nand run a `ninja` build.\n\nNote that seemingly if you change [CMakeLists.txt], you will need to blow away\nthe contents of the `build` directory `rm -rf *`-style because apparently\ndetecting that a crucial configuration file changed is too hard in the 21st\ncentury.  Sigh.\n\nAfter some waiting for compile and link to complete, you should have a binary\nnamed `example` in your `build` directory.  Since you should already have your\ncurrent working directory set to there if you followed the above instructions,\nyou can try your new binary out right away:\n\n```\n./example --help\n```\n\nThis is not much, but will show you that something useful is indeed happening\nin that bundle of machine code.\n\n## Troubleshooting\n\nIt seems reasonable to assume that, after some time passes, this example will\nitself bitrot. Since all LLVM APIs change all the time, chances are that the\nonly really long-term viable way to maintain a tool is to upstream it to LLVM.\nThis is great for generally useful tools, since everyone should benefit from\nthose, and you as author get the benefit of the tool getting continuous\nmaintenance for as long as it is needed.\n\nI thing the general utility of this example is that it shows how to do something\nyou may find useful; so if you find it bitrotted, send a pull request in.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffilmil%2Fclang-tool-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffilmil%2Fclang-tool-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffilmil%2Fclang-tool-example/lists"}