No momento, find_library
direto para a pesquisa de bibliotecas ao longo de LD_LIBRARY_PATH
, em vez de primeiro consultar as bibliotecas carregadas. Uma das 3 implementações atuais:
https://github.com/ros2/rmw_implementation/blob/32c3de1/rmw_implementation/src/functions.cpp#L77
Seria bom se este código preferisse as bibliotecas carregadas atualmente, para suportar o código do aplicativo que não deseja a capacidade de alternar implementações DDS (por exemplo, simplificando casos de reprodução, etc.) em tempo de execução e, em vez disso, vincular RPATH às bibliotecas apropriadas.
Aqui está um protótipo funcional no Linux:
https://github.com/EricCousineau-TRI/rcpputils/commit/b66a3d9e02ace44e6c3b6022eeb3447b121d3311
Cribbing from Drake source:
https://github.com/RobotLocomotion/drake/blob/4c6246197/common/find_loaded_library.cc
Neste commit para este projeto de reprodução do Bazel, agora posso especificar a implementação do RMW no momento da vinculação ou adiar para as variáveis de ambiente:
https://github.com/EricCousineau-TRI/repro/commit/cea11026722b340580257564dc49cb0f59b55178
@ dirk-thomas eu acharia isso extremamente útil. Posso perguntar que evidência (se houver) pode convencê-lo a considerar isso? : D
Posso perguntar que evidência (se houver) pode convencê-lo a considerar isso?
Uma vez que o objetivo de ter uma distro é garantir a estabilidade, os backports são apenas para correção de bugs. As melhorias devem ter como alvo a próxima distro.
Os primeiros pacotes de teste do Dashing devem estar disponíveis na primeira semana de abril.
Sim, parece bom. Aguardará a mesclagem de https://github.com/ros2/rcpputils/issues/3 e, em seguida, enviará para o branch dev. Obrigado!
Temos um nó ros2 que precisa de recursos definidos por meio de setcap
que faz com que LD_LIBRARY_PATH
seja omitido durante a execução. Portanto, estamos definindo RPATH
no binário para encontrar bibliotecas compartilhadas. No entanto, como find_library_path
depende de LD_LIBRARY_PATH
o nó falha com
terminate called after throwing an instance of 'rclcpp::exceptions::RCLError'
what(): failed to initialized rcl init options: failed to find shared library of rmw implementation. Searched rmw_fastrtps_cpp, at /tmp/binarydeb/ros-eloquent-rmw-implementation-0.8.2/src/functions.cpp:130, at /tmp/binarydeb/ros-eloquent-rcl-0.8.3/src/rcl/init_options.c:55
Se bem entendi, a proposta de @EricCousineau-TRI resolveria esse problema. Alguma chance de obter essa funcionalidade na próxima versão? Ou alguma sugestão para uma solução alternativa?
@ EricCousineau-TRI, você está planejando fazer uma iteração sobre isso?
Se bem entendi, a proposta de @EricCousineau-TRI resolveria esse problema.
@wieset Como resolveria o problema se a biblioteca que você está tentando localizar / carregar ainda não estiver carregada?
@ivanpauno Provavelmente não em um futuro próximo (~ 6 meses a 1 ano), infelizmente :(
@ dirk-thomas Eu olhei o código de exemplo de @EricCousineau-TRI e você está certo, isso não resolveria meu problema se a biblioteca ainda não estivesse carregada. Eu acho que poderia vinculá-lo em tempo de compilação para que seja carregado na inicialização do programa.
No entanto, para preservar o carregamento em tempo de execução, vejo duas opções: RPATH
teria que ser pesquisado, que posso definir por meio de CMAKE_INSTALL_RPATH
, ou outra variável de ambiente poderia ser usada em vez de LD_LIBRARY_PATH
, por exemplo, RMW_LIBRARY_PATH
. Mencionei essas duas opções em https://github.com/ros2/rcpputils/issues/40.
@wieset Personalizar sua construção para usar rpath neste caso de uso parece o caminho a seguir.
@ dirk-thomas Concordo, e já estou usando RPATH
para carregar todas as outras bibliotecas. Mas isso não me engana o fato de que find_library_path()
para a biblioteca rmw atualmente não está lá. Ou eu estou esquecendo de alguma coisa?
Mas isso não me engana o fato de que
find_library_path()
para a biblioteca rtw atualmente não está lá.
Você está certo. Eu perdi o contexto neste tíquete.
Eu me pergunto se faz sentido introduzir uma variável de ambiente separada para isso ou se você deve apenas se certificar ao executar executáveis como root para definir as variáveis de ambiente existentes explicitamente.
Até onde eu entendo, LD_LIBRARY_PATH
é completamente ignorado para setcap
/ setuid
executáveis, então configurá-lo sozinho não ajudaria, infelizmente. Veja http://man7.org/linux/man-pages/man8/ld.so.8.html
Não tenho certeza se introduzir uma nova var de ambiente como ROS_LIBRARY_PATH
para contornar essa limitação de segurança é uma boa ideia. ld
só não filtraria isso porque não sabe sobre isso e ignora LD_LIBRARY_PATH
devido a considerações de segurança.
Sinta-se à vontade para propor PRs para adicionar este aprimoramento (conforme indicado pelo rótulo "desejo ajuda").
Vou investigar isso!
Criado uma solicitação pull em https://github.com/ros2/rcpputils/pull/44
FWIW @hidmic , @iantheengineer e eu estamos começando a discutir isso com outras pessoas no TRI. Primeiro para nossos usos internos, depois para integração com coisas como Drake .
Hmm, estou começando a me perguntar por que precisamos de rcpputils::find_library_path()
para começar. Se simplesmente fornecermos rcutils_load_shared_library()
ou seu invólucro rcpputils::SharedLibrary
com um caminho relativo, dlopen
e LoadLibrary
procurarão caminhos e produzirão arquivos de objetos carregados. A documentação de ambos sugere que os arquivos de objeto já carregados não serão puxados novamente. Fazendo isso, RPATHs, LD_LIBRARY_PATHs, RUNPATHs, PATHs e bibliotecas pré-carregadas seriam respeitados por padrão.
CC @ EricCousineau-TRI @wieset @clalancette.
Tudo bem, consulte # 320 e PRs conectados para uma primeira tentativa nisso. @wieset isso deve (indiretamente) resolver seus problemas também. No entanto, essas mudanças tornam rcpputils::find_library_path
obsoleto (para uso em pacotes básicos).
@hidmic Agora que alcançamos o número 320 e amigos, podemos encerrar isso?
Na verdade, podemos. Obrigado pelo solavanco!
Muito obrigado @hidmic , acho que isso me leva a metade do caminho. RUNPATH
ainda precisa ser preenchido corretamente. Vou continuar a discussão com @clalancette em https://github.com/ros2/rcpputils/pull/44.
Comentários muito úteis
Hmm, estou começando a me perguntar por que precisamos de
rcpputils::find_library_path()
para começar. Se simplesmente fornecermosrcutils_load_shared_library()
ou seu invólucrorcpputils::SharedLibrary
com um caminho relativo,dlopen
eLoadLibrary
procurarão caminhos e produzirão arquivos de objetos carregados. A documentação de ambos sugere que os arquivos de objeto já carregados não serão puxados novamente. Fazendo isso, RPATHs, LD_LIBRARY_PATHs, RUNPATHs, PATHs e bibliotecas pré-carregadas seriam respeitados por padrão.CC @ EricCousineau-TRI @wieset @clalancette.