Skip to content

Conversation

@xadaemon
Copy link

@xadaemon xadaemon commented Jan 1, 2026

This patch allows the use of a LLVM prefix instead of system or built in-tree LLVM, this is part of the effort to distribute gnat-llvm in alire.

This patch allows the use of a LLVM prefix instead of system or built
in-tree LLVM, this is part of the effort to distribute gnat-llvm in
alire.
@xadaemon xadaemon force-pushed the llvm-prefix-option branch from 8c6ebbe to 4481069 Compare January 1, 2026 17:46
@sebastianpoeplau
Copy link
Collaborator

Thanks for working on the Alire integration!

If I understand correctly, you're adding a new way to locate LLVM by specifying a path in LLVM_PREFIX. What's not clear to me is how setting LLVM_PREFIX=/some/where/bin is different from using LLVM_BUILD_DIR=/some/where with the current Makefile. I think I'm getting the same results 🤔

@xadaemon
Copy link
Author

xadaemon commented Jan 9, 2026

Thanks for working on the Alire integration!

If I understand correctly, you're adding a new way to locate LLVM by specifying a path in LLVM_PREFIX. What's not clear to me is how setting LLVM_PREFIX=/some/where/bin is different from using LLVM_BUILD_DIR=/some/where with the current Makefile. I think I'm getting the same results 🤔

To be honest, it might be the case I was frustrated because of the many issues I was having with system llvm, and missed that, I would say that just the bit about LLVM_CONFIG is useful in this case then (so you can build with an llvm named like llvm-configure19).
I will update the patch as such then :)

@sebastianpoeplau
Copy link
Collaborator

I would say that just the bit about LLVM_CONFIG is useful in this case then (so you can build with an llvm named like llvm-configure19)

It may even already be possible to do that by setting both LLVM_BUILD_DIR and LLVM_CONFIG; I'm not a Make expert, but I think it lets you override any variable via the environment.

@xadaemon
Copy link
Author

xadaemon commented Jan 9, 2026

I attempted to override the variables via env, and that much I'm sure wasn't working as there's the if that checks if llvm-config exists in LLVM_BUILD_DIR and if not it will fall to the else clause that unpatched would cause the makefile to use llvm-config as a hardcoded value.

@xadaemon
Copy link
Author

xadaemon commented Jan 9, 2026

ifneq ($(wildcard $(LLVM_BUILD_DIR)/bin/llvm-config),)
  LLVM_CONFIG=$(LLVM_BUILD_DIR)/bin/llvm-config
  LLVM_SRC=$(shell cd `$(LLVM_CONFIG) --includedir`/../..;pwd)
  CLANG_CXXFLAGS=-I$(LLVM_BUILD_DIR)/tools/clang/include -I$(LLVM_SRC)/clang/include
else
...

this if to be precise

@sebastianpoeplau
Copy link
Collaborator

Sorry, environment was the wrong word; I usually set them via the command like, as in make LLVM_BUILD_DIR=... LLVM_CONFIG=....

@sebastianpoeplau
Copy link
Collaborator

I guess what I'm trying to say is if you have LLVM installed in /some/where, with llvm-config at /some/where/bin/llvm-config123, then I think you could build with make LLVM_BUILD_DIR=/some/where LLVM_CONFIG=/some/where/bin/llvm-config123. I tried to create a similar scenario locally and it seems to work...

@xadaemon
Copy link
Author

xadaemon commented Jan 9, 2026

yeah, LLVM_BUILD_DIR override should work unpatched, but the system llvm, likely not because of the if, unless and I'm no make expert either, but the wildcard there is without any * for make to expand, and I'm not quite sure if should it be patched to wildcard $(LLVM_BUILD_DIR)/bin/llvm-config* it would still work for the base case of the config program being called llvm-config.

@sebastianpoeplau
Copy link
Collaborator

Oh, now I get it, sorry - bin/llvm-config may not exist in that directory. My test scenario didn't remove it 🤦‍♂️

@sebastianpoeplau
Copy link
Collaborator

I'm just trying to see if there's a way to avoid the duplication between the LLVM_BUILD_DIR case and the one where we set LLVM_CONFIG. What if the build always used LLVM_CONFIG, and the default for it was $(pwd)/../llvm/llvm-obj/bin/llvm-config? Then we wouldn't need LLVM_BUILD_DIR 🤔

@xadaemon
Copy link
Author

xadaemon commented Jan 9, 2026

I'm just trying to see if there's a way to avoid the duplication between the LLVM_BUILD_DIR case and the one where we set LLVM_CONFIG. What if the build always used LLVM_CONFIG, and the default for it was $(pwd)/../llvm/llvm-obj/bin/llvm-config? Then we wouldn't need LLVM_BUILD_DIR 🤔

I can look into making it that way, you have a good point on this.

@xadaemon
Copy link
Author

xadaemon commented Jan 9, 2026

And then the "default" way of building would change to always be make LLVM_CONFIG=/path/to/llvm/here ... unless you want to use the in tree llvm, is that ok?

@sebastianpoeplau
Copy link
Collaborator

That's what I was thinking, yes. Or we could default to llvm-config on the PATH and let people explicitly select the in-tree LLVM 🤷‍♂️

I think this should do it:

LLVM_CONFIG=$(pwd)/../llvm/llvm-obj/bin/llvm-config
CLANG_CXXFLAGS=-I$(shell $(LLVM_CONFIG) --prefix)/tools/clang/include -I$(shell cd `$(LLVM_CONFIG) --includedir`/../..;pwd)/clang/include

Replacing all the checks...

@xadaemon
Copy link
Author

xadaemon commented Jan 9, 2026

I think the default of in tree llvm is less effort for everyday development and if you then need to make proper binaries with out of tree llvm there's a clear path, I guess it's adacore's team choice on this one.

@sebastianpoeplau
Copy link
Collaborator

sebastianpoeplau commented Jan 9, 2026

To be honest, most of us don't use the in-tree LLVM but instead get the latest LLVM artifacts from the internal build servers and activate them via PATH. So let's default to llvm-config on PATH, and I'll make sure to check with the teammates who use the in-tree LLVM.

There's a minor inconvenience still: We always need opt on the PATH because currently it's not called with its full path. Is that a problem for your setup? Fixing it is just a matter of forwarding llvm-config --bindir to the right places, but so far it hasn't been urgent enough 😅 Edit: This might be more of a problem when opt is renamed, e.g. with a suffix...

@xadaemon
Copy link
Author

xadaemon commented Jan 9, 2026

To be honest, most of us don't use the in-tree LLVM but instead get the latest LLVM artifacts from the internal build servers and activate them via PATH. So let's default to llvm-config on PATH, and I'll make sure to check with the teammates who use the in-tree LLVM.

There's a minor inconvenience still: We always need opt on the PATH because currently it's not called with its full path. Is that a problem for your setup? Fixing it is just a matter of forwarding llvm-config --bindir to the right places, but so far it hasn't been urgent enough 😅

I'm not sure I get what you mean by opt in path, you mean like /opt? I just have to understand the issue and I can make the changes. Your proposed replacement worked good build. nvm it fails when you call make from outside the llvm-interface dir.

@xadaemon
Copy link
Author

xadaemon commented Jan 9, 2026

Also, I uderstood your opt comment, forgot there's an llvm binary named opt 🤦🏻.

edit: I looked at the Makefiles but there's not really a call to opt anywhere that I can find.

@xadaemon
Copy link
Author

xadaemon commented Jan 9, 2026

That's what I was thinking, yes. Or we could default to llvm-config on the PATH and let people explicitly select the in-tree LLVM 🤷‍♂️

I think this should do it:

LLVM_CONFIG=$(pwd)/../llvm/llvm-obj/bin/llvm-config
CLANG_CXXFLAGS=-I$(shell $(LLVM_CONFIG) --prefix)/tools/clang/include -I$(shell cd `$(LLVM_CONFIG) --includedir`/../..;pwd)/clang/include

Replacing all the checks...

This doesn't work because the root makefile calls the other makefiles, and this was breaking passing it as a make parameter, I had to make a change so it uses an envvar, check the patch as to how it ended up looking.

@xadaemon
Copy link
Author

xadaemon commented Jan 9, 2026

Also, should I update the readme with new build instructions or do you want to do it on your end?

@sebastianpoeplau
Copy link
Collaborator

the root makefile calls the other makefiles, and this was breaking passing it as a make parameter

I may be misunderstanding, but doesn't Make forward all its variables to child instances? When I run my make LLVM_CONFIG=... command from the repository root it still works, and when I change the value of LLVM_CONFIG in the command line to something bogus then I get errors from llvm-interface.

@xadaemon
Copy link
Author

xadaemon commented Jan 9, 2026

the root makefile calls the other makefiles, and this was breaking passing it as a make parameter

I may be misunderstanding, but doesn't Make forward all its variables to child instances? When I run my make LLVM_CONFIG=... command from the repository root it still works, and when I change the value of LLVM_CONFIG in the command line to something bogus then I get errors from llvm-interface.

Interestingly, for me it fails if I use the patch exactly as you proposed, but with the if I re-inserted it works and builds from the project root 🤷🏻‍♂️.
Make fails with it as a parameter still, even with the if just gets further along, but builds ok with it as env var, just very weird, because indeed make should be forwarding.

@sebastianpoeplau
Copy link
Collaborator

Would you mind sharing the build output when it fails despite the parameter? I'm curious why it should fail 😊

@xadaemon
Copy link
Author

xadaemon commented Jan 9, 2026

make clean
make LLVM_CONFIG=$HOME/.local/opt/llvm-19.1.7/bin/llvm-config -j

stderr:
make_out.log

from what I can tell it is breaking at linking for some weird reason.

@sebastianpoeplau
Copy link
Collaborator

sebastianpoeplau commented Jan 9, 2026

Which include paths does it pass to the compiler at the very beginning of the log, when we build llvm_wrapper.cc? I think there's an assumption in the patch that the build directory is inside the source directory, but I don't see why this would only be a problem when llvm-config is located via a Make parameter.

Also, the first line of your log is a complaint that obj/def_*.h can't be found. Those files should be created by check_for_llvm_apis.sh at the beginning of the build; do you see any error output from the script?

@xadaemon
Copy link
Author

xadaemon commented Jan 9, 2026

Which include paths does it pass to the compiler at the very beginning of the log, when we build llvm_wrapper.cc? I think there's an assumption in the patch that the build directory is inside the source directory, but I don't see why this would only be a problem when llvm-config is located via a Make parameter.

Also, the first line of your log is a complaint that obj/def_*.h can't be found. Those files should be created by check_for_llvm_apis.sh at the beginning of the build; do you see any error output from the script?

I will check too, but if you are interested, here is the full output
make_out.log

edit:
This is the only reference during the whole build to the script.

/check_for_llvm_apis.sh "/home/mx/.local/opt/llvm-19.1.7/bin/llvm-config"
cat: 'obj/def_*.h': No such file or directory

@xadaemon
Copy link
Author

xadaemon commented Jan 9, 2026

And for debug sake, here is a success build:
cmd:

LLVM_CONFIG=$HOME/.local/opt/llvm-19.1.7/bin/llvm-config make

build_ok.log

edit: looking at this log the same issue with check_for_llvm_apis.sh is present and the build still goes through.

@sebastianpoeplau
Copy link
Collaborator

I tried to compare the build commands for llvm_wrapper.cc between the failing build and the one that succeeds, but curiously there's no build command in the log of the successful build. Is it possible that that one didn't start with a clean environment?

@xadaemon
Copy link
Author

xadaemon commented Jan 9, 2026

I tried to compare the build commands for llvm_wrapper.cc between the failing build and the one that succeeds, but curiously there's no build command in the log of the successful build. Is it possible that that one didn't start with a clean environment?

I made sure to run make clean between builds, but to make sure here is the command:

make clean; LLVM_CONFIG=$HOME/.local/opt/llvm-19.1.7/bin/llvm-config make 2>&1 | tee good.log

and the log
good.log

@sebastianpoeplau
Copy link
Collaborator

The build command for llvm_wrapper.cc is almost the same for this last log and the failure log you sent above - the only difference is the lack of -O2 in the successful run. But I see now that llvm_wrapper.cc wasn't actually the reason for the failure, it only causes warnings. Regarding those warnings and also the lack of obj/def_*.h, are the include paths correct?

  • /home/mx/.local/opt/llvm-19.1.7/tools/clang/include
  • /home/mx/.local/opt/clang/include

As for why the build with the Make parameter failed, I now suspect that it's something unrelated: We've occasionally seen race conditions somewhere in the build system when it's run with -j. Would you mind retrying the Make parameter case without parallelism?

@xadaemon
Copy link
Author

xadaemon commented Jan 9, 2026

The build command for llvm_wrapper.cc is almost the same for this last log and the failure log you sent above - the only difference is the lack of -O2 in the successful run. But I see now that llvm_wrapper.cc wasn't actually the reason for the failure, it only causes warnings. Regarding those warnings and also the lack of obj/def_*.h, are the include paths correct?

  • /home/mx/.local/opt/llvm-19.1.7/tools/clang/include
  • /home/mx/.local/opt/clang/include

As for why the build with the Make parameter failed, I now suspect that it's something unrelated: We've occasionally seen race conditions somewhere in the build system when it's run with -j. Would you mind retrying the Make parameter case without parallelism?

I will try without '-j', and no the second path is wrong, I will double check the makefile and the paths.

@xadaemon
Copy link
Author

xadaemon commented Jan 9, 2026

Ok, building without -j makes the build work, interestingly enough the build with LLVM_CONFIG as env var never failed despite -j and the one with it as parameter never worked, until now without -j, interesting...
also I just realized the envvar way I was building without -j, I feel stupid for that one 🤦🏻‍♂️ mb.

@xadaemon
Copy link
Author

xadaemon commented Jan 9, 2026

There this should be a good final version of the patch, it builds reliably and I also fixed the include paths.

@sebastianpoeplau
Copy link
Collaborator

I'm not sure about the include paths:

CLANG_CXXFLAGS=-I$(shell `$(LLVM_CONFIG) --includedir`)/clang

When I run a build locally, this line gets the include dir from llvm-config but then tries to interpret it as a shell command:

/bin/sh: 1: /my/llvm/install/include: Permission denied

I think the reason why the build still works is that the directory layout differs between LLVM installations and build trees:

  • In an installation, the Clang headers that we need are already in llvm-config --includedir, which is part of the build command anyway. So everything works even without CLANG_CXXFLAGS.
  • In a build tree, llvm-config --includedir points to the llvm/include subdirectory of the LLVM sources. The Clang headers are in clang/include though, so the build fails. I guess we'll need to make sure that CLANG_CXXFLAGS is correct in this case. The good news is that I think we no longer need tools/clang/include from the build directory: It used to contain required (generated) headers with earlier versions of LLVM, but that doesn't seem to be the case anymore.

If you confirm that your build works with an LLVM installation even with empty CLANG_CXXFLAGS, I can take care of fixing the flags for build trees (unless you have one lying around and feel like it 🙃).

@xadaemon
Copy link
Author

xadaemon commented Jan 9, 2026

I'm not sure about the include paths:

CLANG_CXXFLAGS=-I$(shell `$(LLVM_CONFIG) --includedir`)/clang

When I run a build locally, this line gets the include dir from llvm-config but then tries to interpret it as a shell command:

/bin/sh: 1: /my/llvm/install/include: Permission denied

I think the reason why the build still works is that the directory layout differs between LLVM installations and build trees:

  • In an installation, the Clang headers that we need are already in llvm-config --includedir, which is part of the build command anyway. So everything works even without CLANG_CXXFLAGS.
  • In a build tree, llvm-config --includedir points to the llvm/include subdirectory of the LLVM sources. The Clang headers are in clang/include though, so the build fails. I guess we'll need to make sure that CLANG_CXXFLAGS is correct in this case. The good news is that I think we no longer need tools/clang/include from the build directory: It used to contain required (generated) headers with earlier versions of LLVM, but that doesn't seem to be the case anymore.

If you confirm that your build works with an LLVM installation even with empty CLANG_CXXFLAGS, I can take care of fixing the flags for build trees (unless you have one lying around and feel like it 🙃).

Hey, yeah, it works, with CLANG_CXXFLAGS=, I still have the tree from the llvm builds I made sitting around, so if you want I can look into making that work, just need to figure out how we would differentiate between a tree or an install.

@xadaemon
Copy link
Author

xadaemon commented Jan 9, 2026

Also do you want to put that in a separate patchset or keep it in this one?

@sebastianpoeplau
Copy link
Collaborator

I think we'll have to fix it as part of this one because the old code worked with a build tree, whereas the proposed new version doesn't.

I'm not sure that we actually need to detect build trees specifically. Since the installation case works without any special flags, we could assume a build tree and set CLANG_CXXFLAGS accordingly as long as the directories in question exist.

@xadaemon
Copy link
Author

I think we'll have to fix it as part of this one because the old code worked with a build tree, whereas the proposed new version doesn't.

I'm not sure that we actually need to detect build trees specifically. Since the installation case works without any special flags, we could assume a build tree and set CLANG_CXXFLAGS accordingly as long as the directories in question exist.

Ok, I will look into it tomorrow :)

@sebastianpoeplau sebastianpoeplau self-assigned this Jan 16, 2026
@sebastianpoeplau
Copy link
Collaborator

sebastianpoeplau commented Jan 16, 2026

I think this should work (in addition to your changes in the other files):

LLVM_CONFIG ?= llvm-config

# If llvm-config belongs to an installation of LLVM, then its include directory
# is going to contain everything we need. Otherwise, if llvm-config belongs to a
# _build tree_, we need to add an extra directory because the Clang headers
# won't be in `llvm-config --includedir`.
CLANG_CXXFLAGS :=
CLANG_INCLUDE_DIR := $(abspath $(shell $(LLVM_CONFIG) --includedir)/../../clang/include)

ifneq ($(wildcard $(CLANG_INCLUDE_DIR)/.),)
  CLANG_CXXFLAGS := -I$(CLANG_INCLUDE_DIR) -I$(abspath $(shell $(LLVM_CONFIG) --obj-root)/tools/clang/include)
endif

It turned out that we do need <build_dir>/tools/clang/include because it contains clang/Basic/DiagnosticGroups.inc, a transitive dependency of our C++ code.

I tried this with both an LLVM installation and a build tree, setting only LLVM_CONFIG. The variable can be set via the command line or the environment. Would you mind checking whether it works in your setup too?

@xadaemon
Copy link
Author

xadaemon commented Jan 17, 2026 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants