Adding a command to generate the env information for linking #8021

Closed
wants to merge 1 commit into
from

Projects

None yet

8 participants

@ashgti

Adding a command to generate the env information for linking for linking aginst a library. This is useful for keg_only formula and for generating the correct -I and -L information for any formula including its dependencies.

Basically, if I have an external project that I don't want to put in homebrew but I would like to link against a keg_only formula, this script could help me generate the env variables needed to build my project.

@Sharpie

Looks useful---I will review when I get the chance.

@ashgti

So, an example of how one might use this. For instance, say I want to use brew's keg only libiconv for whatever reason. I could install it as per usual, then do:

$ cd /path/to/my/project
$ brew env-info libiconv | xargs env make

It will set:
CC="/usr/llvm-gcc-4.2/bin/llvm-gcc-4.2"
CXX="/usr/llvm-gcc-4.2/bin/llvm-g++-4.2"
LD="/usr/llvm-gcc-4.2/bin/llvm-gcc-4.2"
CFLAGS="-O3 -march=core2 -msse4.1 -w -pipe"
CXXFLAGS="-O3 -march=core2 -msse4.1 -w -pipe"
CPPFLAGS="-I/usr/local/Cellar/libiconv/1.14/include"
LDFLAGS="-L/usr/local/Cellar/libiconv/1.14/lib"
MAKEFLAGS="-j2"

So now my include path should include libiconv from the keg as well as the right lib directory for linking. It would still be up to me to link against the library and deal with any issues when a keg is shadowing a built-in library. It should also be pretty easy to parse this output and append it to a Makefile.

Anyway, just thought I would show a bit of the motivation for this command. I'll try to write a --help for it as well.

@jacknagel jacknagel commented on an outdated diff Oct 12, 2011
Library/Contributions/examples/brew-env-info.rb
@@ -0,0 +1,89 @@
+require 'formula'
+require 'extend/ENV'
+require 'hardware'
+
+ENV_VARIABLES = %w[ CC CXX LD CFLAGS CXXFLAGS CPPFLAGS LDFLAGS MAKEFLAGS
+ MACOSX_DEPLOYMENT_TARGET PKG_CONFIG_PATH HOMEBREW_DEBUG
+ HOMEBREW_VERBOSE HOMEBREW_USE_CLANG HOMEBREW_USE_GCC
+ HOMEBREW_USE_LLVM HOMEBREW_SVN PATH CMAKE_LIBRARY_PATH ]
@jacknagel
jacknagel Oct 12, 2011

The HOMEBREW_ environment variables aren't really useful in this context, no?

@ashgti

@jacknagel Good point, they really are not useful for this command. I just copied the whole list from the cmd/--env.rb file. I'll take those out.

@wjwwood wjwwood added a commit that referenced this pull request Oct 24, 2011
@ashgti ashgti Adding in the ability to specify the specific flags you want to print…
…. In case you only need a subset of the ENV variables.

Closes #8021.

Signed-off-by: William Woodall <wjwwood@gmail.com>
d7f8623
@adamv

Probably needs to be squashed to a single commit for review

@ashgti

Squashed the commits.

@MikeMcQuaid
Homebrew member

Does brew --env not already pretty much do this? We could either edit the output of that command or add another option to output in a format suitable for source or eval.

@wjwwood

brew --env doesn't give the keg paths like CPPFLAGS="-I/usr/local/Cellar/libiconv/1.14/include" for example.

When I run something like this:

∫ brew info readline
readline 6.2.2
http://tiswww.case.edu/php/chet/readline/rltop.html

This formula is keg-only.
OS X provides the BSD libedit library, which shadows libreadline.
In order to prevent conflicts when programs look for libreadline we are
defaulting this GNU Readline installation to keg-only.

/usr/local/Cellar/readline/6.2.2 (30 files, 1.7M)
https://github.com/mxcl/homebrew/commits/master/Library/Formula/readline.rb

∫ brew --env readline
CC: /usr/bin/clang
CXX: /usr/bin/clang++ => /usr/bin/clang
LD: /usr/bin/clang
CFLAGS: -Os -w -pipe -march=native -Qunused-arguments
CXXFLAGS: -Os -w -pipe -march=native -Qunused-arguments
MAKEFLAGS: -j4

This doesn't tell me anything about how to compile and link against the keg-only readline formula.

The use case as I understood it was to provide an easy mechanism for having your source projects find the flags needed to compile and link against keg-only formulae outside of Homebrew.

@MikeMcQuaid
Homebrew member

Perhaps we should modify brew --env to work the way that is useful rather than adding another very similar command.

@ashgti

I could work my changes into brew --env, should I make a new branch/pull request or should I just modify this one?

@jacknagel

Anything that goes into brew --env would have to be much less complex than this; I don't think we want 15 options to the --env switch. I think brew --env <formula> is about as far as we'd want to go.

IMO an external command is the place to start with this, and the most useful things can be ported to brew --env eventually.

@MikeMcQuaid
Homebrew member

@jacknagel Is there any reason we can't use the same output format? The only difference I see is the LDFLAGS, CPPFLAGS and output format. If we change the output format then we don't need any flag changes; brew --env formula could do what is desired here and brew --env could either just output what it currently does or output what it currently does in the new shell-friendly format.

@jacknagel

brew --env already gives output suitable for machine consumption when stdout is not a tty, e.g. so it can be sourced.

@MikeMcQuaid
Homebrew member

Neat. Then I definitely think we just want support for brew --env <formula> and that should match the functionality here.

@ashgti Just modify this pull request, thanks. As said you probably just need to add the LDFLAGS and CPPFLAGS when you specify a formula.

@samueljohn

@ashgti would be cool if you could do that!

@ashgti

I squashed this into a simple extension of brew --env so you can add formula to brew --env. If you do brew --env readline (which is keg only), it now extends CPPFLAGS and LDFLAGS to include the paths to the keg, which was the main objective of this command to begin with.

@samueljohn

It displays
CPPFLAGS: /usr/local/Cellar/readline/6.2.2/include
shoudn't there be an "-I" in front?
Similar for LDFLAGS.

@samueljohn

@jacknagel how would I source the output of brew --env? Piping it so source doesn't work. I am too stupid.

@samueljohn

Further, the CPPFLAGS and LDFLAGS from homebrew are overwritten by your changes. Compare brew --env with brew --env readline on a homebre not at /usr/local or on a homebrew without the command line tools . Could you append instead of replacing the CPPFLAGS and LDFLAGS?

Something along the lines:

    ARGV.formulae.each do |f|
      ENV.append "CPPFLAGS", "-I#{f.include}"
      ENV.append "LDFLAGS", "-L#{f.lib}"
    end
@jacknagel
$ brew --env >/tmp/foo
$ source /tmp/foo
@samueljohn

Ok, thanks :-)

@ashgti

I updated it to append instead of override LDFLAGS and CPPFLAGS

@ashgti

I added a guard if formula.keg_only? and made it prepend the path instead of append, this way, if you say, for example, brew --env readline it puts readline in front so you get it instead of the system version. Otherwise you still have the system path listed before the keg path.

@samueljohn

Great. Is prepending the action that is done when I add a keg-only formula, too?

@ashgti

It only appends keg only formula, if its not keg only then just having /usr/local/include and /usr/local/lib is enough for you to find and link to the libraries. The path /usr/local is at the end of the list, here's a better example:

$ brew --env readline sdl > /tmp/my-flags
$ cat /tmp/my-flags
export CC="/usr/bin/clang"
export CXX="/usr/bin/clang++"
export LD="/usr/bin/clang"
export CFLAGS="-Os -w -pipe -march=native -Qunused-arguments -mmacosx-version-min=10.7"
export CXXFLAGS="-Os -w -pipe -march=native -Qunused-arguments -mmacosx-version-min=10.7"
export CPPFLAGS="-I/usr/local/Cellar/readline/6.2.2/include -isystem /usr/local/include"
export LDFLAGS="-L/usr/local/Cellar/readline/6.2.2/lib -L/usr/local/lib"
export MACOSX_DEPLOYMENT_TARGET="10.7"
export MAKEFLAGS="-j8"
export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig/:/usr/local/share/pkgconfig:"

Here if you wanted to link your project against say readline (which is keg only) and sdl (which is not) it will give you this set of CPPFLAGS/LDFLAGS. Then, you can either export these flags or add them to a make file and things should hopefully work correctly. All of the SDL includes should be in /usr/local/include since its not keg-only.

@samueljohn

I just want to make sure that the content of the env flags are ordered the same way as homebrew uses internally, otherwise it may be bad for debugging linking errors etc..

@adamv

In fact code should be refactored to ensure that they are the same, though that's perhaps a bigger piece of work.

@ashgti

https://github.com/mxcl/homebrew/blob/master/Library/Homebrew/build.rb#L64 In the build.rb file ENV.prepend is used if its keg_only?. So, thats what I am trying to copy. I only added the CPPFLAGS and LDFLAGS, but there are a few other options that are set for normal dependency builds, such as PKG_CONFIG_PATH, ACLOCAL_PATH and PATH.

@samueljohn
@ashgti ashgti Extending `brew --env` to include formula info
Extending `brew --env` to include formula include paths so you can easily find keg only formula from outside of brew.
ba4e250
@samueljohn

The new commit looks good. For now, this is what we want to have. For the future, we want to refactor the code ... but until then... :-)

@mxcl
Homebrew member

brew --env sort of supports this now. But only for superenv. It wouldn't be hard to make it work for std-env.

For superenv you can also do:

brew sh

And it will start a shell with all keg-only kegs set up in the environment for building.

@adamv

@mxcl - reject this?

@MikeMcQuaid
Homebrew member

Rejecting as it's supported by brew sh.

@MikeMcQuaid MikeMcQuaid closed this Feb 1, 2013
@xu-cheng xu-cheng locked and limited conversation to collaborators Feb 16, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.