Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

sambler
Copy link

@sambler sambler commented Apr 1, 2025

Hi, currently on FreeBSD wxStandardPaths::GetExecutablePath returns an empty string, this update fills in the right path.

Question - where would I add -lprocstat to wx-config --libs output when run on FreeBSD?

Copy link
Contributor

@vadz vadz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding this code, but, indeed, support for it needs to be added to the build system too:

  1. You need to add new compile-time option wxHAS_PROCSTAT (you may choose a better name if you have one, of course), i.e. add it to the "Unix-specific options" section of setup.h.in and build/cmake/setup.h.in.
  2. You should add AC_CHECK_LIB(procstat, procstat_getpathname) (this assumes that all the other functions are always available in that library if this one is) to configure.ac and add -lprocstat to WXCONFIG_LIBS and AC_DEFINE(wxHAS_PROCSTAT) if the check succeeds.
  3. For CMake, I'm not sure how exactly to do it, to be honest, but I think you might use FIND_LIBRARY().

if (n_proc != 1)
break;

procstat_getpathname(ps, procs, pathname, sizeof(pathname));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we check the return value of this one, i.e. compare it with 0?

break;

procstat_getpathname(ps, procs, pathname, sizeof(pathname));
} while (false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The do/while(false) hack is rather ugly and unnecessary in C++ code. It would be nicer to rewrite this without, e.g.

auto* const ps = procstat_open_sysctl();
if (!ps)
    return wxStandardPathsBase::GetExecutablePath();
wxON_BLOCK_EXIT1(procstat_close, ps);

auto* const procs = procstat_getprocs();
if (!procs)
    return wxStandardPathsBase::GetExecutablePath();
wxON_BLOCK_EXIT2(procstat_freeprocs, ps, procs);

if (procstat_getpathname(ps, procs, pathname, sizeof(pathname)) != 0)
    return wxStandardPathsBase::GetExecutablePath();

return pathname;

@vadz vadz added work needed Too useful to close, but can't be applied in current state WIP and removed WIP labels Apr 1, 2025
sambler added 4 commits April 2, 2025 20:39
add lib to wx-config --libs output
and define wxHAS_PROCSTAT in cxxflags
use wxON_BLOCK_EXIT to cleanup allocated structs
test for wxHAS_PROCSTAT being defined through configure steps
@sambler
Copy link
Author

sambler commented Apr 2, 2025

I have refactored the GetExecutablePath code.
adjusted configure.ac, build using configure/make works for me.
started an attempt at adding into cmake but have not had any luck building with cmake yet. Any tips here would be appreciated.

Copy link
Contributor

@vadz vadz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this looks much better, but there is some confusion between wxUSE_PROCSTAT and wxHAS_PROCSTAT: I've suggested the latter to test for procstat stuff presence in the library code, and this is the only place where it's needed, so there is no need to add it to wx-config --cxxflags output. Also, it's not a user-settable option (unless we want to allow disabling it by using --disable-procstat with configure, but I don't think it's worth it) it, so wxUSE_PROCSTAT is not needed at all. Finally, wxHAS_XXX constants are, by convention, either defined (as 1) or not, they should never be defined as 0.

As for CMake, I'm not sure what is the problem exactly?

P.S. Oh, sorry, and I forgot to say, but configure needs to be regenerated by running autoconf (ideally using autoconf-for-wx container with the fixed autoconf version, but you can do it using your autoconf version too, I'll just rerun it before merging then), otherwise your changes are not even tested in the FreeBSD CI job.

#include "wx/textfile.h"

#if defined( __LINUX__ ) || defined( __VMS )
#include <unistd.h>
#endif

#if defined(__FreeBSD__)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be

Suggested change
#if defined(__FreeBSD__)
#ifdef wxHAS_PROCSTAT

@@ -167,6 +177,28 @@ wxString wxStandardPaths::GetExecutablePath() const

if ( !exeStr.empty() )
return exeStr;
#elif defined(__FreeBSD__) && wxHAS_PROCSTAT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this

Suggested change
#elif defined(__FreeBSD__) && wxHAS_PROCSTAT
#elif defined(wxHAS_PROCSTAT)


// procstat_freeprocs should be called before procstat_close
wxON_BLOCK_EXIT2(procstat_freeprocs, ps, procs);
wxON_BLOCK_EXIT1(procstat_close, ps);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line needs to be moved above (before procs initialization), otherwise procstat_close() won't be called if procstat_getprocs() fails and we return early.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

procstat_close needs to be called after procstat_freeprocs so that ps is still valid in the procstat_freeprocs call. I was thinking code execution order, but the destructors would be run while clearing the stack, so that would be lifo making the first code line the last to run, which would work.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if I'm missing something, but yes, exactly: because the dtors run in the opposite order, you have to put the guard for procstat_close() before the one for procstat_freeprocs().

configure.ac Outdated
@@ -7732,6 +7751,11 @@ case "$wxUSE_ZLIB" in
;;
esac

if test "$wxUSE_PROCSTAT" = "yes"; then
WXCONFIG_CXXFLAGS="$WXCONFIG_CXXFLAGS -DwxHAS_PROCSTAT=1"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be necessary: wxHAS_PROCSTAT is only used internally.

Suggested change
WXCONFIG_CXXFLAGS="$WXCONFIG_CXXFLAGS -DwxHAS_PROCSTAT=1"

/*
On FreeBSD use libprocstat to get executable path name.
*/
#cmakedefine01 wxHAS_PROCSTAT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#cmakedefine01 wxHAS_PROCSTAT
#cmakedefine wxHAS_PROCSTAT

configure.ac Outdated
@@ -200,6 +200,7 @@ case "${host}" in
AC_DEFINE(__FREEBSD__)
AC_DEFINE(__BSD__)
DEFAULT_DEFAULT_wxUSE_GTK=1
wxUSE_PROCSTAT=yes
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is needed at all, we already check for host before testing for procstat below.

configure.ac Outdated
*-*-freebsd*)
AC_MSG_CHECKING([for libprocstat])
AC_CHECK_LIB(procstat, procstat_getpathname, [
PROCSTAT_LINK=" -L/usr/lib -lprocstat"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is -L/usr/lib really needed? I'd expect the linked to look in this directory by default.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When building static libs, the libs and app built and found the lib in /usr/lib but when building the shared libs linking failed with unable to find libprocstat so I added -L/usr/lib

@@ -22,6 +22,7 @@ USE_GUI=@wxUSE_GUI_bf@
USE_HTML=@wxUSE_HTML_bf@
USE_MEDIA=@wxUSE_MEDIA_bf@
USE_OPENGL=@wxUSE_OPENGL_bf@
USE_PROCSTAT=@wxUSE_PROCSTAT_bf@
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need this.

@sambler
Copy link
Author

sambler commented Apr 2, 2025

I discovered the need to run autoconf, I didn't commit configure changes as there are a lot, I expect from different autoconf vers.

@vadz
Copy link
Contributor

vadz commented Apr 2, 2025

I discovered the need to run autoconf, I didn't commit configure changes as there are a lot, I expect from different autoconf vers.

Yes, this is why using the container image mentioned above is best, but if this can't be done, it's still better to regenerate it to at least test compiling this code in the FreeBSD CI job.

sambler added 2 commits April 3, 2025 09:53
remove define in cxxflags
rearrange placement of wxON_BLOCK_EXIT
@sambler
Copy link
Author

sambler commented Apr 2, 2025

Also of note, I'm not sure the lib tests need to go into configure, it would appear that freebsd is the only system using libprocstat, FreeBSD > 9.0 will always have it, searching man pages for procstat_* functions for netbsd, openbsd, dragonfly, darwin all come up empty.


if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
wx_lib_link_libraries(wxbase PUBLIC "-lprocstat")
target_compile_definitions(wxbase PRIVATE "-DwxHAS_PROCSTAT")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We normally don't use compile definitions. Everything is added to setup.h[.in].
Most of the items there are named HAVE_[NAME], so in this case HAVE_PROCSTAT .

To integrate it in CMake, I think you can add a check in setup.cmake to check if the header is available:

check_include_file(libprocstat.h HAVE_PROCSTAT)

This will set HAVE_PROCSTAT to 1 if it is available, and if setup.h.in contains this variable, it will be automatically set in the generated setup.h.

And then in base/CmakeLists.txt

if (HAVE_PROCSTAT)
    wx_lib_link_libraries(wxbase PUBLIC "-lprocstat")
endif()

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything I can think of trying with cmake has failed, using cmake 3.31.6. I think mainly due to the inability to include libprocstat.h by itself. I tried check_include_files with the list of includes needed but that has failed as well.

Using find_library in cmake does work, but still need to use target_compile_definitions to define it when compiling.

Every FreeBSD release since 9.0 (released 2012) has had libprocstat and headers. The searches I have done show FreeBSD as the only one using libprocstat. So just testing for FreeBSD will ensure the headers and lib exists, it isn't an optional component and no other system appears to have it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll need to update setup.h.in too. With the patch below, the CMake build works for me (the library can be PRIVATE and doesn't need -l prefix). I also couldn't get check_include_files to work.

I used wxHAVE_PROCSTAT name because you also use this name in stdpaths.cpp.

For configure, I think you can just replace CXXFLAGS="${CXXFLAGS} -DwxHAVE_PROCSTAT" with AC_DEFINE(wxHAVE_PROCSTAT), but I have not tested this.

 build/cmake/lib/base/CMakeLists.txt | 5 +++++
 build/cmake/setup.h.in              | 3 +++
 setup.h.in                          | 3 +++
 src/png                             | 2 +-
 src/webp                            | 0
 5 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/build/cmake/lib/base/CMakeLists.txt b/build/cmake/lib/base/CMakeLists.txt
index 7f60e93f527..32507f919c6 100644
--- a/build/cmake/lib/base/CMakeLists.txt
+++ b/build/cmake/lib/base/CMakeLists.txt
@@ -52,6 +52,11 @@ if(wxUSE_THREADS AND CMAKE_THREAD_LIBS_INIT)
     wx_lib_link_libraries(wxbase PRIVATE ${CMAKE_THREAD_LIBS_INIT})
 endif()
 
+if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
+    set(wxHAVE_PROCSTAT 1)
+    wx_lib_link_libraries(wxbase PRIVATE "procstat")
+endif()
+
 if(APPLE)
     wx_lib_link_libraries(wxbase
         PUBLIC
diff --git a/build/cmake/setup.h.in b/build/cmake/setup.h.in
index 952dcb68a49..d469368809b 100644
--- a/build/cmake/setup.h.in
+++ b/build/cmake/setup.h.in
@@ -908,6 +908,9 @@
 /* Define if you have wcsnlen() function */
 #cmakedefine wxHAVE_WCSNLEN 1
 
+/* define if you have procstat (FreeBSD) */
+#cmakedefine wxHAVE_PROCSTAT 1
+
 /* The number of bytes in a wchar_t.  */
 @SIZEOF_WCHAR_T_CODE@
 
diff --git a/setup.h.in b/setup.h.in
index 5d65c131a09..870cf9819eb 100644
--- a/setup.h.in
+++ b/setup.h.in
@@ -907,6 +907,9 @@
 /* Define if you have wcsnlen() function */
 #undef wxHAVE_WCSNLEN
 
+/* define if you have procstat (FreeBSD) */
+#undef wxHAVE_PROCSTAT
+
 /* The number of bytes in a wchar_t.  */
 #undef SIZEOF_WCHAR_T

@sambler
Copy link
Author

sambler commented Apr 7, 2025

@MaartenBent using set have procstat works, only if it is in setup.cmake.

I see two issues, the second would need to be addressed in a different issue.

  1. wx-config output. When I build static libs -lprocstat is in the --libs output, when I build shared libs it is not. This applies to both cmake and autoconf builds.

This means with static libs, building the samples, demos and utils works. (except wxrc which I need to manually add -lprocstat to LDFLAGS to build)

With shared libs, the libs build but the apps fail without -lprocstat in LDFLAGS.

  1. I can't get cmake to compile the shared libs. The static libs do build (not in one pass).

This would appear to be dependencies, shared libs fail to link with libs that haven't compiled yet. Although, base linking to gtk libs doesn't sound right to me.

[  4%] Linking CXX shared library ../../lib/libwx_baseu-3.3.so
ld: error: unable to find library -lwx_gtk3u_xrc-3.3
ld: error: unable to find library -lwx_gtk3u_html-3.3
ld: error: unable to find library -lwx_gtk3u_qa-3.3
ld: error: unable to find library -lwx_gtk3u_core-3.3
ld: error: unable to find library -lwx_baseu_xml-3.3
ld: error: unable to find library -lwx_baseu_net-3.3
ld: error: unable to find library -lwx_baseu-3.3

@MaartenBent
Copy link
Contributor

using set have procstat works, only if it is in setup.cmake

I guess this makes sense. lib/base/CMakeLists.txt is in a sub_directory, so the define might be in the wrong scope. Not sure why it worked for me, maybe an old cached value. Or maybe it didn't work at all and compiled without procstat. I'll try to test it again some time.

I have no idea what is happening with the libraries it tries to link to. For me building the wxbase and console sample targets worked fine and had no link issues.

I did have to add some extra CMake flags, similar to what is needed in CI, to make everything work, but this was related to finding system libraries, not wx libraries:

wxWidgets/.cirrus.yml

Lines 67 to 71 in 5bc736d

# We need to pass these flags so that libraries under /usr/local are found,
# because configure doesn't look for them there by default (it ought to
# always use pkg-config instead, but it currently doesn't do this either).
CPPFLAGS=-I/usr/local/include
LDFLAGS=-L/usr/local/lib

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
work needed Too useful to close, but can't be applied in current state
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants