Open SpaceIm opened 2 years ago
Hi, the new environment mechanism in develop2 should work just fine for these cases, because all the environment is wrapped in a "bat" or "sh" launcher, then the self.run
command is composed like "conanrun.sh && command" so the SIP shouldn't affect.
The SIP issues come when calling an executable in a protected location of the operating system, like "bash" but if you activate the environment inside the bash and before calling the command it is ok.
I cant' find a specific test for Autotools and SIP but we are building shared libraries and running the test package (with cmake) in some of them.
Ok, I didn't look at those tests, but I would advice these ones for CMake & autotools:
CMake:
Test 1 (VirtualBuildEnv + CMakeToolchain + CMake helper):
create a recipe A packaging a shared lib
create a recipe B packaging an executable depending on shared lib of recipe A (requirement).
create a CMake based test package having recipe B in build_requirements, and using add_custom_command()
in its CMakeLists to run executable of recipe B. (*)
It should succeed at build time.
Test 2 (VirtualRunEnv + CMakeToolchain + CMake helper):
create a recipe A packaging a shared lib
create a CMake based test package having recipe A in requirements, and using try_run()
in its CMakeLists with a src file linking to shared lib of recipe A. (*)
It should succeed at configuration time.
Autotools
Test 1 (VirtualRunEnv + AutotoolsToolchain + AutotoolsDeps + Autotools helper):
create a recipe A packaging a shared lib.
create an Autotools based test package having recipe A in requirements. (*)
It should succeed at configure time
(*) These tests could ensure that VirtualRunEnv/VirtualBuildEnv context are injected only when it matters (for example in autotools test 1, configure needs VirtualRunEnv, but it doesn't matter at build or installation time). I have to say that I have no idea in the new model how you inject VirtualRunEnv/VirtualBuildEnv for specific commands.
Other comment: for these tests, ensure to not inject paths of shared libs into RPATH of executables, otherwise tests would be biased.
Some CMake (new toolchain) + shared can be found in:
to not inject paths of shared libs into RPATH of executables
Those tests will do whatever the CMakeToolchain is doing by default, I think they are now not injecting any rpaths
Ok thanks for the link. I think they don't test what I'm talking about.
For example I see:
client.run("install app/0.1@ -o chat:shared=True -o hello:shared=True -g VirtualRunEnv")
command = environment_wrap_command("conanrun", "app", cwd=client.current_folder)
client.run_command(command)
So here you test what we are doing with self.run("app", run_environment=True)
in conan v1. But I would like to know if we can inject env vars of VirtualBuildEnv and/or VirtualRunEnv in build helpers (and eventually to specific commands of build helpers), and it they survive to SIP.
Basically I have no idea how to achieve those injections looking at the documentation. I would have expected something like:
cmake = CMake()
cmake.configure(VirtualBuildEnv=True) # for example here pkg_check_modules() is used, so we have pkgconf in build_requirements(), but it may have been linked to pkgconf shared, so we need build context env vars at configure time.
cmake.build(VirtualBuildEnv=True) # here we may have another build requirement called at build time through a add_custom_command(), and we don't know whether it is linked or not to a shared lib, so we also want build context env vars.
But it doesn't seem to be that simple.
Those tests will do whatever the CMakeToolchain is doing by default, I think they are now not injecting any rpaths
By default, CMake populates RPATH/RUNPATH/LC_RPATH of shared libs and executables in the build tree with paths of dependencies, then cleanup RPATH during installation. So it's not just about conan.
@SpaceIm could you take a stab are writing a test to cover this use case you see?
I'd love to see it ❤️
Since I still don't understand how VirtualBuildEnv
& VirtualRunEnv
interact with new (or old) build helpers, I won't be able to write these tests. I don't even fully understand layout()
and its scope/side effects in source()
, build()
, package()
and package_info()
, and interaction with tools like replace_in_file etc.
Answering myself:
CMake & add_custom_command()
:
SIP issues in add_custom_command()
of CMake builds don't come from conan, and I don't think conan can do anything against it.
I've tested a manual export of DYLD_LIBRARY_PATH
in terminal, then in the same terminal a manual CMake configuration & build (with a add_custom_command()
calling an executable linked to a shared lib, this shared lib not being installed at system level but under a conan recipe folder).
The call of the executable fails at build time because shared lib is not found by the loader.
If I add shared lib folder to LC_RPATH
of this executable, it works obviously, but conan can't rely on this.
It means that VirtualBuildEnv
won't fix this specific case. I don't know whether it's something coming from:
cmake --build
If you try to print DYLD_LIBRARY_PATH
:
message(STATUS "DYLD_LIBRARY_PATH: $ENV{DYLD_LIBRARY_PATH}"
in CMakeLists): content preserved, so I guess any executable linked to a shared lib & called at configure time should work with VirtualBuildEnv
.echo ${DYLD_LIBRARY_PATH}
before the command calling the executable): emptyAutotools:
Autotools build with "all shared" can be fixed by injecting VirtualRunEnv
in build scope if not cross building (I'm not 100% sure, I've tested in a recipe having zlib & openssl as dependencies, and test executable in configure may have found my system installed libs).
Revisiting this old issue - the short answer is that the SIP issue does not come from Conan - although troubleshooting this is complicated.
The System Integrity protection will "purge" the DYLD_
variables when launching "protected" processes, as per https://developer.apple.com/library/archive/documentation/Security/Conceptual/System_Integrity_Protection_Guide/RuntimeProtections/RuntimeProtections.html#//apple_ref/doc/uid/TP40016462-CH3-SW1
As far as I can see, protected processes are in /bin
and /usr/bin
, affecting programs that are used during the build such as /usr/bin/make
and /bin/sh
- unsure if it applies to all the executables in those directories, but I'm assuming it does.
The "process tree" will usually look like:
Conan (Python interpreter) invokes a shell -> sources conanbuildenv.sh
(which sets DYLD_LIBRARY_PATH
) -> invokes CMake -> CMake will see DYLD_LIBRARY_PATH
during configure
During "build"
Conan -> shell -> source conanbuildenv -> invoke CMake (cmake --build) or make directly -> make -> make will invoke commands in /bin/sh
For the above, the DYLD_LIBRARY_PATH
will be purged if:
CMAKE_MAKE_PROGRAM
is /usr/bin/make
- then nothing inside the build process will see that variable anymore, and anything that requires to work correctly will fail./bin/sh
(or /bin/zsh
or /bin/bash
) What we've been able to observe:
If a user GNU Make installed in homebrew, CMake will prefer /opt/homebrew/bin/gmake
instead of /usr/bin
- so this is now unaffected (gmake will not purge the variable)
But make (whether it comes from Apple or from homebrew) implicitly uses /bin/sh
as the shell, regardless of the SHELL
environment variable (see docs) - so technically this should also cause it to fail (this is very well described here: https://hynek.me/articles/macos-dyld-env/), even if one is using a gnu make from outside of /usr/bin/make
.
However, what I've observed, and I need to fully confirm this - is that make
does not always fork into a shell process - in some cases it appears to launch things directly, which is good (as it bypasses the issue). So most of the cases I've seen, if CMake uses GNU make from homebrew, the issues "go away" (alternatively, one can also invoke the make inside an Xcode installation path, which is also not inside /usr/bin
)
Autotools build with "all shared" can be fixed by injecting VirtualRunEnv in build scope if not cross building (I'm not 100% sure, I've tested in a recipe having zlib & openssl as dependencies, and test executable in configure may have found my system installed libs).
This is an entirely different issue altogether - and will also be an issue on Linux
We have had reported issues in Conan Center due to this workaround, when the "host" dependency graph contains libraries that happen to be used by tools invoked by autotools (e.g. the compiler itself) - as we are exposing Conan libraries to system executables. In order to avoid that, it's possible to cause the linker to emit -rpath
only at configure time, so that the executables can run without LD_LIBRARY_PATH
, but Im not fully convinced... https://github.com/conan-io/conan-center-index/pull/24702/files
In conan-center, a common issue on macOS is "all shared" build of autotools based recipes.
What happen:
AutotoolsBuildEnvironment
helper since underlying build system is autotoolsshared
optionconan install <recipename/version>@ "*":shared=True -b
configure
script is executed, there are hard errors for native builds while executingconftest
executable: shared dependencies cannot be located by the loader on macOS. On Linux it works fine AFAIK.There are 2 workarounds:
autotools.libs = []
, but for complex recipes where dependencies are not found throughPKG_CHECK_MODULES
, it's not an option.configure
on the fly to inject something likeexport DYLD_LIBRATY_PATH=<all libdirs of conan dependencies>
(and here we are interested onrequires
by the way) inside this script (see https://github.com/conan-io/conan-center-index/pull/8635/commits/fde36dee223125ce35f574d6b48f75e8e259fe4f). Indeed, any attempt to injectDYLD_LIBRATY_PATH
with something likevirtualenv
/VirtualRunEnv
doesn't work,DYLD_LIBRATY_PATH
is reinitialized somewhere by SIP beforeconfigure
execution.Question: does this
DYLD_LIBRATY_PATH
reinitialization by SIP come from the way conan callsconfigure
in its autotools helpers or not (it relies onself.run
under the hood)? Do you see this issue in the new helper? Is there a functional test for this case?